我希望automapper为视图模型生成URL。例如,这是我的数据对象:
public class User
{
public int Id { get; set; }
public int Name { get; set; }
}
视图模型如下所示:
public class UserListItem
{
public string Name { get; set; }
public string EditUrl { get; set; }
}
我希望使用为应用程序定义的路由生成EditUrl
属性。
这样的事情:
listIten.EditUrl = Url.Action("Edit", "UserController", new { id = user.Id });
似乎无法让AutoMapper执行此操作。没有RequestContext,UrlHelper或任何可用于映射表达式的东西,我在调用Mapper.Map时没有找到任何传递上下文的方法。
我错过了什么吗?或者首先想要这样做是不是一个坏主意?
更新:其他背景
我正在研究为MVC视图生成URL的替代方法,目的是使ASP.NET MVC应用程序维护尽可能简单。映射视图模型时生成URL是其中一种选择。它很容易测试和清理视图。在某些情况下,它还会促进视图的可重用性。在尝试这个想法时,我遇到了一个砖墙,AutoMapper无法接受Map
操作的任何类型(动态)上下文。
答案 0 :(得分:7)
我认为这不是AutoMapper的工作。
路由是特定于ASP.NET的,AutoMapper实际上只适用于对象映射。它没有HTTP上下文的可见性(也不应该),因此无法完成。
如果你想在多个地方“重复使用”这个逻辑,为什么不创建一个强类型的HTML助手呢?
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 });
}
查看:强>
@Html.EditUserLinkForModel()
虽然这甚至可能有点过分。这是1班轮! :)
答案 1 :(得分:4)
虽然这种方法会导致大量可测试性问题,但可以使用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)));
这会使测试变得困难但是你可以通过注入一个提供UrlHelper的类来解决这个问题。然后,如果可以模拟URL帮助程序,那么可以减轻测试问题或至少删除对HttpContext的依赖性。
答案 2 :(得分:2)
以为我在这个主题上分享了我的发现......我使用自定义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";
}
}
您可以将ObjectToUrlConverter子类化为您希望转换为URL的任何对象。 接下来,为要转换为URL的每个对象创建Map:
Mapper.CreateMap<SomeEntity, string>().ConvertUsing<SomeEntityToUrlConverter>();
最后,映射如下。 Url
是UrlHelper的实例。
Mapper.Map<SourceObject[], DestinationObject[]>(items, opts => opts.Items.Add("Url", Url));
SourceObject中SomeEntity类型的任何属性现在都可以正确转换为目标字符串属性,作为URL。