Add prefix to EditorFor for all elements

1k views Asked by At

I have the following model:

public class CaseFormViewModel
{
    public int ID { get; set; }
    public int AppID { get; set; }

    public CaseGeneralFormViewModel General { get; set; }

    public CaseMedicalFormViewModel Medical { get; set; }

    public CaseLegalFormViewModel Legal { get; set; }

    public CaseCommentsFormViewModel Comments { get; set; }

    public List<UploadedDocumentModel> Attachments { get; set; }

    public string AzureStorage { get; set; }

}

public class CaseGeneralFormViewModel : CaseGeneralViewModelBase
{
    [Required]
    public new string PatientName { get; set; }

also I have a view with model CaseFormViewModel and have a Partial View with model CaseGeneralFormViewModel. View loads this partial View:

@Html.Partial("PartialCaseGeneralForm", Model.General)

Partial View has the following string:

@Html.ValidationMessageFor(model => model.PatientName)

then, when I post this view to the controller method:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult UpdateCase(int AppID, CHFN.Models.CaseFormViewModel model)
    {

model.General is null. I understand why, because PatientName should have id="General.PatientName" instead of id="PatientName", but how can I add that prefix to the all elements on page?

I see some ability to do it : modify post controller method to:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult UpdateCase(int AppID, CaseGeneralFormViewModel general)
    {

but first at all, code is dirty (structure of internal classes are broken), secondly - any class (i.e. CaseGeneralFormViewModel) can have 2 properties of the same class (i.e.

public Class1 Prop1 { get; set; }
public Class1 Prop2 { get; set; }

). How to solve it - I don't know....

2

There are 2 answers

0
Oleg Sh On

Solution is:

Create an extention method for Partial:

public static MvcHtmlString PartialFor<TModel, TProperty>(
      this HtmlHelper<TModel> helper,
      System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, 
      string partialViewName)

{
       var name = ExpressionHelper.GetExpressionText(expression);
       var model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
       var viewData = new ViewDataDictionary(helper.ViewData)
       {
            TemplateInfo = new System.Web.Mvc.TemplateInfo
            {
                HtmlFieldPrefix = name
            }
       };
       return helper.Partial(partialViewName, model, viewData);
}

and use:

@Html.PartialFor(m=>m.General,"PartialCaseGeneralForm")
0
JJS On

In asp.net core mvc

public static class HtmlHelperPartialExtensions
{
    public static IHtmlContent PartialWithPrefix(this IHtmlHelper htmlHelper, string partialViewName, object model, string prefix)
    {
        var htmlFieldPrefix = (string.Empty.Equals(prefix) ? "." : "") + prefix;
        return htmlHelper.Partial(partialViewName, model, new ViewDataDictionary(htmlHelper.ViewData) { TemplateInfo = { HtmlFieldPrefix = htmlFieldPrefix } });
    }

    public static Task<IHtmlContent> PartialWithPrefixAsync(this IHtmlHelper htmlHelper, string partialViewName, object model, string prefix)
    {
        var htmlFieldPrefix = (string.Empty.Equals(prefix) ? "." : "") + prefix;
        return htmlHelper.PartialAsync(partialViewName, model, new ViewDataDictionary(htmlHelper.ViewData) {TemplateInfo = {HtmlFieldPrefix = htmlFieldPrefix}});
    }

    public static IHtmlContent PartialWithPrefixFor<TModel, TProperty>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
        string prefix = ExpressionHelper.GetExpressionText(expression);
        object model = ExpressionMetadataProvider.FromLambdaExpression(expression, helper.ViewData, helper.MetadataProvider).Model;
        return PartialWithPrefix(helper, partialViewName, model, prefix);
    }

    public static Task<IHtmlContent> PartialWithPrefixForAsync<TModel, TProperty>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
        string prefix = ExpressionHelper.GetExpressionText(expression);
        object model = ExpressionMetadataProvider.FromLambdaExpression(expression, helper.ViewData, helper.MetadataProvider).Model;
        return PartialWithPrefixAsync(helper, partialViewName, model, prefix);
    }
}