【问题标题】:Pass sub object to partial view from views with different models, have it bind when form is posted将子对象从具有不同模型的视图传递到部分视图,在发布表单时将其绑定
【发布时间】:2020-10-14 11:35:44
【问题描述】:

我有一个 ASP.net MVC Core 2(如果需要可以升级到 3)网络应用程序。

有几个不同的类,房东、租户、承包商 - 它们每个都有一个地址对象和其他不同的属性。

我有一个从每个视图传递地址对象的局部视图。

<partial name="_AddressPartial" , model="@Model" />

这很好用。但是当表单发布时,每个地址字段都是平铺的,因为地址的名称是“Street”之类的东西,而不是“Address.Street”——因为地址模型被传递给部分。所以模型绑定器正在寻找“街道”等,而不是作为地址对象的一部分。

我可以从部分所在的每个页面传递对象,并添加前缀“地址”。到每个字段名称,但房东、承包商、租户等都是不同的类,所以我需要每页有一个不同的部分,这违背了这一点。

我也许可以使用带地址的基类,然后从中派生所有其他类,并将基类绑定到部分?但这似乎只是为了获得部分工作。

我可以将 Address 对象展平到每个 ViewModel 中——尽管这样在写入数据库时​​会产生更多的工作(你不能只向 Dapper 传递一个 Address 模型,你必须手动编写一些 SQL 来进行更新) ,并产生大量重复。

如何在所有页面之间重复使用部分,保持干燥,并避免列出的问题。

我已经用谷歌搜索过了,以上就是我能找到的所有内容。我错过了什么吗?

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc asp.net-core-2.0 asp.net-core-3.1 asp.net-core-mvc-2.0


    【解决方案1】:

    我参加聚会有点晚了,但我认为您应该在partial 元素中使用属性for 而不是model,类似于:

    <partial name="_AddressPartial" for="@Model.Address" />
    

    假设Model.Address 是一个存储共享Address 类实例的属性。因此,ASP.NET Core 将正确映射字段名称与前缀 Address

    【讨论】:

      【解决方案2】:

      当表单发布时,每个地址字段都是平铺发布的,因为地址的名称类似于“Street”,而不是“Address.Street”——因为地址模型被传递给部分。所以模型绑定器正在寻找“街道”等,而不是作为地址对象的一部分。

      要修复它,您可以尝试以下方法。

      方法1:在_AddressPartial.cshtml 中设置HtmlFieldPrefix"Address",如下所示。

      @model Address
      
      @{ 
          Html.ViewData.TemplateInfo.HtmlFieldPrefix = "Address"; 
      }
      <div class="form-group">
          <label asp-for="City" class="control-label"></label>
          <input asp-for="City" class="form-control" />
          <span asp-validation-for="City" class="text-danger"></span>
      </div>
      <div class="form-group">
          <label asp-for="Street" class="control-label"></label>
          <input asp-for="Street" class="form-control" />
          <span asp-validation-for="Street" class="text-danger"></span>
      </div>
      
      @*other input fields*@
      

      方法 2:实现 custom model binder 将数据绑定到 Street 等属性。

      地址类

      public class Address
      {
          public string City { get; set; }
      
          public string Street { get; set; }
      }
      

      自定义模型绑定AddressBinder

      // code logic here
      // ...
      
      var model = new Address();
      
      if (bindingContext.ValueProvider.GetValue("City").FirstOrDefault() != null&& bindingContext.ValueProvider.GetValue("Street").FirstOrDefault() != null)
      {
          var city = bindingContext.ValueProvider.GetValue("City").FirstOrDefault();
          var street = bindingContext.ValueProvider.GetValue("Street").FirstOrDefault();
      
          model.City = city;
          model.Street = street;
      }
      
      
      bindingContext.Result = ModelBindingResult.Success(model);
      return Task.CompletedTask;
      

      将其应用于Address 属性

      [ModelBinder(BinderType = typeof(AddressBinder))]
      public Address Address { get; set; }
      

      测试和结果

      对于方法 1:

      <div class="row">
          <div class="col-md-4">
              <form asp-action="NewContractor">
                  <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                  <div class="form-group">
                      <label asp-for="Cname" class="control-label"></label>
                      <input asp-for="Cname" class="form-control" />
                      <span asp-validation-for="Cname" class="text-danger"></span>
                  </div>
                  <partial name="_AddressPartial" model="@Model" />
                  <div class="form-group">
                      <input type="submit" value="Create" class="btn btn-primary" />
                  </div>
              </form>
          </div>
      </div> 
      

      对于方法 2:

      public class Landlord
      {
          public string Name { get; set; }
          [ModelBinder(BinderType = typeof(AddressBinder))]
          public Address Address { get; set; }
      }
      

      【讨论】:

      • 有趣的想法,最后我在保存地址的页面顶部创建了一个“通用”容器对象。我在 Razor 页面的顶部将地址值传递给它。然后我将同一个对象传递给每个不同页面的局部视图。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多