0

In my application, I have a few modal windows. Each of them takes the same partial view and the same view model, but displays other data. For that, I generate a dynamic HtmlFieldPrefix as to not have multiple IDs of the same name. Example:


@foreach (var product in Model.Products)
{
    string buyModalId = product.BuyModel.BindingPrefix;
    @await Html.PartialForAsync("_BuyForm", product.BuyModel, buyModalId)
}

BindingPrefix contains a dynamically added string (for example buy-product-{ID}). In my view I also have a hidden field that is supposed to POST the binding prefix back:

@Html.Hidden(nameof(Model.BindingPrefix), Model.BindingPrefix)

(Source: Asp.Net MVC Dynamic Model Binding Prefix)

That does not work, however, since the binding prefix is null when POSTing, too. Hence await TryUpdateModelAsync(model, model.BindingPrefix); in my controller fails.

The code for the Html.PartialForAsync method is the following:

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

(Source: MVC 6 VNext how to set HtmlFieldPrefix?)

What am I missing? Why is my model still null? When removing the binding prefix, the binding works flawlessly - but the browser throws warnings regarding multiple same IDs.

SeToY
  • 5,777
  • 12
  • 54
  • 94

1 Answers1

0

Found the answer by using a custom model binder inside my model:

public override void BindModel(ModelBindingContext bindingContext)
{
    var providers = bindingContext.ValueProvider as System.Collections.IList;
    var formProvider = providers?.OfType<JQueryFormValueProvider>().FirstOrDefault();
    if (formProvider != null)
    {
        var (_, value) = formProvider.GetKeysFromPrefix(string.Empty).First();
        bindingContext.BinderModelName = value;
        bindingContext.FieldName = value;
        bindingContext.ModelName = value;
    }

    base.BindModel(bindingContext);
}
SeToY
  • 5,777
  • 12
  • 54
  • 94