automapper可以生成url吗?

时间:2011-06-21 09:31:17

标签: c# asp.net-mvc automapper

我希望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操作的任何类型(动态)上下文。

3 个答案:

答案 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。