强类型的html助手,具有不同的get和post模型

时间:2012-02-19 22:44:38

标签: asp.net-mvc

如果Get Action返回带有“Car”模型的视图。视图显示来自对象的信息,并将输入发送到表单内的另一个操作,该操作采用“付款”类型的对象

视图上的模型是Car类型,它为我提供了强大的html支持和一些其他功能,如displaytext。但是对于发布我没有像TextBox那样的Htmlhelper支持(x => x.amount我需要使它像@Html.TextBox(“Amount”... 它可能,但这是唯一的选择吗?

5 个答案:

答案 0 :(得分:9)

你可以这样做:

@{
var paymentHtml = Html.HtmlHelperFor<Payment>();
}

@paymentHtml.EditorFor(p => p.Amount)

使用此扩展方法:

public static class HtmlHelperFactoryExtensions {

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper) {
      return HtmlHelperFor(htmlHelper, default(TModel));
   }

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper, TModel model) {
      return HtmlHelperFor(htmlHelper, model, null);
   }

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper, TModel model, string htmlFieldPrefix) {

      var viewDataContainer = CreateViewDataContainer(htmlHelper.ViewData, model);

      TemplateInfo templateInfo = viewDataContainer.ViewData.TemplateInfo;

      if (!String.IsNullOrEmpty(htmlFieldPrefix))
         templateInfo.HtmlFieldPrefix = templateInfo.GetFullHtmlFieldName(htmlFieldPrefix);

      ViewContext viewContext = htmlHelper.ViewContext;
      ViewContext newViewContext = new ViewContext(viewContext.Controller.ControllerContext, viewContext.View, viewDataContainer.ViewData, viewContext.TempData, viewContext.Writer);

      return new HtmlHelper<TModel>(newViewContext, viewDataContainer, htmlHelper.RouteCollection);
   }

   static IViewDataContainer CreateViewDataContainer(ViewDataDictionary viewData, object model) {

      var newViewData = new ViewDataDictionary(viewData) {
         Model = model
      };

      newViewData.TemplateInfo = new TemplateInfo { 
         HtmlFieldPrefix = newViewData.TemplateInfo.HtmlFieldPrefix 
      };

      return new ViewDataContainer {
         ViewData = newViewData
      };
   }

   class ViewDataContainer : IViewDataContainer {

      public ViewDataDictionary ViewData { get; set; }
   }
}

答案 1 :(得分:5)

如果我正确地理解了你的问题,那么我刚刚为我的一个项目编写了一些类似代码的代码。它并不需要像Max Toro所建议的那样特别的东西。

@{
    var teamHelper = new HtmlHelper<Team>(ViewContext, this);
}

@using (teamHelper.BeginForm())
{
    @teamHelper.LabelFor(p => p.Name)
    @teamHelper.EditorFor(p => p.Name)  
}

答案 2 :(得分:1)

除了Max Toro的实现之外,如果你有一个非null模型但没有静态类型信息(这两个方法需要嵌入到Max提供的实现中),这里还有几个。

当您动态检索模型的属性名称并且需要调用采用名称而不是表达式的非泛型HtmlHelper方法时,这些方法很有效:

@Html.TextBox(propertyName)

例如。

    public static HtmlHelper HtmlHelperFor( this HtmlHelper htmlHelper, object model )
    {
        return HtmlHelperFor( htmlHelper, model, null );
    }

    public static HtmlHelper HtmlHelperFor( this HtmlHelper htmlHelper, object model, string htmlFieldPrefix )
    {
        var t = model.GetType();
        var viewDataContainer = CreateViewDataContainer( htmlHelper.ViewData, model );

        TemplateInfo templateInfo = viewDataContainer.ViewData.TemplateInfo;

        if( !String.IsNullOrEmpty( htmlFieldPrefix ) )
            templateInfo.HtmlFieldPrefix = templateInfo.GetFullHtmlFieldName( htmlFieldPrefix );

        ViewContext viewContext = htmlHelper.ViewContext;
        ViewContext newViewContext = new ViewContext( viewContext.Controller.ControllerContext, viewContext.View, viewDataContainer.ViewData, viewContext.TempData, viewContext.Writer );

        var gt = typeof( HtmlHelper<> ).MakeGenericType( t );

        return Activator.CreateInstance( gt, newViewContext, viewDataContainer, htmlHelper.RouteCollection ) as HtmlHelper;
    }

答案 3 :(得分:0)

如果我理解您的问题,请尝试:

@Html.EditorFor(x => x.Amount)

您还可以为付款创建编辑器模板。有关执行此操作的详细信息,请参阅this page

如果我误解了,一些示例代码可能会有所帮助。

答案 4 :(得分:0)

对于ASP.NET Core 2

public static class HtmlHelperFactoryExtensions
{
    public static IHtmlHelper<TModel> HtmlHelperFor<TModel>(this IHtmlHelper htmlHelper)
    {
        return HtmlHelperFor(htmlHelper, default(TModel));
    }

    public static IHtmlHelper<TModel> HtmlHelperFor<TModel>(this IHtmlHelper htmlHelper, TModel model)
    {
        return HtmlHelperFor(htmlHelper, model, null);
    }

    public static IHtmlHelper<TModel> HtmlHelperFor<TModel>(this IHtmlHelper htmlHelper, TModel model, string htmlFieldPrefix)
    {
        ViewDataDictionary<TModel> newViewData;
        var runtimeType = htmlHelper.ViewData.ModelMetadata.ModelType;
        if (runtimeType != null && typeof(TModel) != runtimeType && typeof(TModel).IsAssignableFrom(runtimeType))
        {
            newViewData = new ViewDataDictionary<TModel>(htmlHelper.ViewData, model);
        }
        else
        {
            newViewData = new ViewDataDictionary<TModel>(htmlHelper.MetadataProvider, new ModelStateDictionary())
            {
                Model = model
            };
        }

        if (!String.IsNullOrEmpty(htmlFieldPrefix))
            newViewData.TemplateInfo.HtmlFieldPrefix = newViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldPrefix);

        ViewContext newViewContext = new ViewContext(htmlHelper.ViewContext, htmlHelper.ViewContext.View, newViewData, htmlHelper.ViewContext.Writer);

        var newHtmlHelper = htmlHelper.ViewContext.HttpContext.RequestServices.GetRequiredService<IHtmlHelper<TModel>>();
        ((HtmlHelper<TModel>)newHtmlHelper).Contextualize(newViewContext);
        return newHtmlHelper;
    }
}
相关问题