【问题标题】:Mvc Bind custom form fieldsMvc 绑定自定义表单字段
【发布时间】:2017-08-02 19:17:29
【问题描述】:

我正在尝试将自定义表单字段绑定到现有 ViewModel。 我有一个与此类似的 ViewModel

public class BasicProfileViewModel {
   public Employee Employee { get; set; }
}

我正在使用上述方法加载我的表单,但我还有一个 CustomFormFieldComponent,它添加了自定义表单字段

这基于 Employee 模型中的一些值

 @await Component.InvokeAsync("CustomFormFields", new { Model.Level, Model.Employee.CompanyId, Model.Employee.EmployeeId })

该组件非常简单,只需返回我从数据库中检索到的列表

@model List<CustomFormField>

@for (int i = 0; i < Model.Count(); i++)
{
  <div class="row">

    <div class="form-group form-material col-md-6">

      @Html.LabelForModel(Model[i].FieldLabel, new { @class = "form-control-label" })
      @if (Model[i].IsMandatory)
      {
        <span>*</span>
      }

      @if (Model[i].DropdownValues.Any())
      {
        var values = new SelectList(Model[i].DropdownValues);
        <select asp-items="@values" class="form-control"></select>
      }
      else
      {
        @Html.TextBoxFor(m => Model[i].FieldValue, new { @class = "form-control" })
      }
    </div>

  </div>
}

如何将这些自定义表单字段作为 ViewModel 的一部分?

我正在考虑做一个自定义模型绑定器,Employee 是一个复杂的对象,因此使用反射设置值并不那么简单。而且我什至还没有开始使用自定义表单字段。

public class RequestBasicProfile
    {
        public Employee Employee { get; set; } = new Employee();
        public List<CustomFormField> FormFields { get; set; }
    }
    public class RequestBasicProfileBinder : IModelBinder
        {
            public Task BindModelAsync(ModelBindingContext bindingContext)
            {
                if (bindingContext == null)
                {
                    throw new ArgumentNullException(nameof(bindingContext));
                }

                var result = new RequestBasicProfile();

                foreach (var item in bindingContext.HttpContext.Request.Form)
                {

                    var propertyInfo = result.Employee.GetType().GetProperty(item.Key.Replace("Employee.", ""));
                    if (propertyInfo != null)
                    {
                        var value = item.Value[0];
                        propertyInfo.SetValue(result.Employee, Convert.ChangeType(value, propertyInfo.PropertyType), null);
                    }
                }

                bindingContext.Result = ModelBindingResult.Success(result);
                return Task.CompletedTask;
            }
        }

【问题讨论】:

    标签: .net-core model-binding imodelbinder


    【解决方案1】:

    原来我是想把事情弄得过于复杂。当我意识到 MVC 如何处理数据绑定时,它就容易多了。所以我最终只是做了以下事情

    须藤代码

    型号

    public classs MyViewModel
    {
      public string EmpFirstName { get; set; }
      public string EmpMiddleName { get; set; }
    
      // custom form fields
      public List<FormFieldDto> Fields { get; set; }
    }
    

    剃须刀

    @Html.EditorFor(m => m.Employee.EmpFirstName)
    @Html.EditorFor(m => m.Employee.EmpMiddleName)
    @for (var i = 0; i < Model.Count; i++){
        <input type="text" name="@Model[i].Id" />
    }
    

    诀窍是确保生成的名称与您的模型匹配

    name="MyViewModel.EmpFirstName" // will get generated correctly
    name="MyViewModel.EmpMiddleName" // will get generated correctly
    name="MyViewModel.Fields[0].FieldValue" //might have to manually change the name depending on how your object looks
    name="MyViewModel.Fields[2].FieldValue" //might have to manually change the name depending on how your object looks
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      • 2014-01-12
      • 2017-12-17
      相关资源
      最近更新 更多