Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can automapper generate url's?

I would like automapper to generate URL's for a view model. For example, this is my data object:

public class User
{
  public int Id { get; set; }
  public int Name { get; set; }
}

The view model looks something like this:

public class UserListItem
{
  public string Name { get; set; }
  public string EditUrl { get; set; }
}

I would like the EditUrl property to be generated using the routes defined for the application.

Something like this:

listIten.EditUrl = Url.Action("Edit", "UserController", new { id = user.Id });

There seems to be no way to get AutoMapper to do this. There is no RequestContext, UrlHelper or anything available for mapping expressions and I haven't found any way to pass in context when invoking Mapper.Map.

Am I missing something? Or is it just a bad idea to want to do this in the first place?

Update: Additional background

I'm investigating alternative ways of generating URLs for MVC views with the aim of making ASP.NET MVC application maintenance as easy as possible. Generating URLs while mapping the viewmodels is one of the alternatives. It's easy to test and cleans up the view. It would also promote view re-usability in some cases. While trying out this idea I ran into a brick wall with AutoMapper not being able to accept any kind of (dynamic) context for a Map operation.

like image 583
Marnix van Valen Avatar asked Jun 21 '11 09:06

Marnix van Valen


2 Answers

I would argue this isn't AutoMapper's job.

Routing is ASP.NET specific, AutoMapper's really only good for object mapping. It has no visibility of the HTTP Context (nor should it), so it can't be done.

If you want to "re-use" this logic across multiple places, why not create a strongly-typed HTML helper?

public static MvcHtmlString EditUserLinkForModel<UserListItem>(this HtmlHelper<UserListItem> htmlHelper)
{
   var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
   return urlHelper.Action("Edit", 
                           "UserController", 
                           new { id = htmlHelper.ViewData.Model.UserId });
}

View:

@Html.EditUserLinkForModel()

Although even that's probably overkill. It's a 1 liner! :)

like image 86
RPM1984 Avatar answered Sep 18 '22 21:09

RPM1984


Although this approach causes a host of testability issues it is possible to do what you want... utilizing HttpContext.Current.Request.RequestContext.

Mapper.CreateMap<Sample1, Sample2>().ForMember(
                destination => destination.Url, options => options.MapFrom(source => new UrlHelper(HttpContext.Current.Request.RequestContext).Content(source.Url)));

This would make testing difficult but you can get around that by injecting a class that provides the UrlHelper. Then if the URL helper can be mocked out then your testing issues are mitigated or at least the dependency on HttpContext it removed.

like image 40
John Sobolewski Avatar answered Sep 19 '22 21:09

John Sobolewski