Сильно типизированный HTML-помощник с другой моделью для получения и публикации - PullRequest
7 голосов
/ 20 февраля 2012

Если действие Get возвращает вид с моделью "Car".Представление отображает информацию об объекте и принимает входные данные для публикации в форме в другое действие, которое принимает объект типа «Платеж»

Модель в представлении имеет тип Car и предоставляет мне поддержку html со строгими типами и некоторыедругие функции, такие как displaytext.Но для публикации я не поддерживаю Htmlhelper, например TextBox (x => x.amount. Мне нужно сделать так, чтобы @ Html.TextBox ("Amount" ... Это возможно, но это единственный вариант?

Ответы [ 5 ]

9 голосов
/ 20 февраля 2012

Вы можете сделать это:

@{
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; }
   }
}
5 голосов
/ 29 мая 2012

Если я правильно понимаю ваш вопрос, вот код, который я только что написал для одного из моих проектов, чтобы сделать что-то подобное. Это не требует ничего особенного, как то, что было предложено Максом Торо.

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

@using (teamHelper.BeginForm())
{
    @teamHelper.LabelFor(p => p.Name)
    @teamHelper.EditorFor(p => p.Name)  
}
1 голос
/ 26 августа 2016

В дополнение к реализации Максом Торо, вот еще пара примеров, когда у вас есть ненулевая модель, но нет статической информации о типе (эти два метода должны быть встроены в реализацию, которую предоставляет Макс).

Эти методы хорошо работают, когда вы динамически извлекаете имена свойств для модели, и вам нужно вызывать неуниверсальные методы 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;
    }
0 голосов
/ 11 июля 2019

Для 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;
    }
}
0 голосов
/ 20 февраля 2012

Если я правильно понимаю вашу проблему, попробуйте:

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

Вы также можете создать шаблон редактора для оплаты. См. эту страницу для получения подробной информации об этом.

Если я неправильно понимаю, может помочь пример кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...