Can automapper generate urls?

I would like automapper to generate the url for the 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 EditUrl created using the routes defined for the application.

Something like that:

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

There seems to be no way to get AutoMapper for this. There is no RequestContext, UrlHelper or anything available to display expressions, and I have not found a way to pass the context when calling Mapper.Map.

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

Update: additional background

I’m exploring alternative ways to generate URLs for MVC views in order to make ASP.NET MVC application maintenance as easy as possible. Creating URLs when mapping viewmodels is one alternative. Easy to check and clear presentation. In some cases, this would also facilitate reuse. Having tried this idea, I came across a brick wall when AutoMapper was unable to accept any (dynamic) context for the Map operation.

+6
source share
3 answers

I would say that this is not the work of AutoMapper.

Routing is specific to ASP.NET, AutoMapper is really only suitable for mapping objects. It does not have HTTP context visibility (and should not), so this is not possible.

If you want to "reuse" this logic in several 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 this is probably overkill. This is 1 liner! :)

+7
source

Although this approach causes a lot of testability problems, you can do what you want ... using 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 will make testing difficult, but you can get around this by introducing a class that UrlHelper provides. Then, if the URL helper can be mocked, your testing problems will be mitigated, or at least depending on the HttpContext being removed.

+4
source

I just thought that I shared my conclusions on this topic ... I solved the problem as follows, using a special TypeConverter (AutoMapper 3.1.1):

 public abstract class ObjectToUrlConverter<Source> : ITypeConverter<Source, string> { public string Convert(ResolutionContext context) { UrlHelper Url = (UrlHelper)context.Options.Items["Url"]; string result = null; if (context.SourceValue != null) { result = Url.Link(GetRouteName(), GetControllerName(), GetIdentifier((Source)context.SourceValue)); } return result; } public abstract object GetIdentifier(Source sourceObject); public abstract string GetRouteName(); public abstract string GetControllerName(); } public class SomeEntityToUrlConverter : ObjectToUrlConverter<SomeEntity> { public override object GetIdentifier(SomeEntity sourceObject) { return sourceObject.Id; } public override string GetRouteName() { return "someRouteName"; } public override string GetControllerName() { return "someControllerName"; } } 

You can subclass ObjectToUrlConverter for any object that you want to convert to a URL. Then create a map for each object that you want to convert to a URL:

 Mapper.CreateMap<SomeEntity, string>().ConvertUsing<SomeEntityToUrlConverter>(); 

And finally, let's draw as follows. Url is an instance of UrlHelper.

 Mapper.Map<SourceObject[], DestinationObject[]>(items, opts => opts.Items.Add("Url", Url)); 

Any property in SourceObject that is of type SomeEntity can now be correctly converted to a target string property as a URL.

+2
source

Source: https://habr.com/ru/post/890994/


All Articles