我正在尝试构建一个"新客户"表单,所以我使用默认模型绑定器来构建我的Customer对象:
public ActionResult New(Customer customer) { ... }
Run Code Online (Sandbox Code Playgroud)
唯一的问题是我在Customer对象上有一些不需要的属性.当我将这些字段留空时,ASP.NET MVC会自动抛出模型错误,指出"需要一个值".
如何向框架发出这些属性是可选的信号?
这是我的自定义模型绑定器.我将断点设置为BindModel但不会被此控制器操作触发:
public ActionResult Create(TabGroup tabGroup)
Run Code Online (Sandbox Code Playgroud)
...
public class BaseContentObjectCommonPropertiesBinder : DefaultModelBinder
{
public new object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
BaseContentObject obj = (BaseContentObject)base.BindModel(controllerContext, bindingContext);
obj.Modified = DateTime.Now;
obj.Created = DateTime.Now;
obj.ModifiedBy = obj.CreatedBy = controllerContext.HttpContext.User.Identity.Name;
return obj;
}
Run Code Online (Sandbox Code Playgroud)
我的注册:
//尝试了这两行
ModelBinders.Binders[typeof(TabGroup)] = new BaseContentObjectCommonPropertiesBinder();
ModelBinders.Binders.Add(typeof(TabGroup), new BaseContentObjectCommonPropertiesBinder());
Run Code Online (Sandbox Code Playgroud) 鉴于使用以下视图模型和操作DefaultModelBinder,它似乎忽略了字典,但正确绑定了所有其他属性.我在这里错过了什么吗?看一下MVC源代码,这似乎是合法的.
谢谢
public class SomeViewModel
{
public SomeViewModel()
{
SomeDictionary = new Dictionary<string, object>();
}
public string SomeString { get; set; }
public IDictionary<string, object> SomeDictionary { get; set; }
}
[HttpPost]
public ActionResult MyAction(SomeViewModel someViewModel)
{
//someViewModel.SomeString binds correctly
//someViewModel.SomeDictionary is null
}
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<SomeViewModel>" MasterPageFile="~/Views/Shared/Site.Master" %>
<asp:Content runat="server" ID="Content2" ContentPlaceHolderID="MainContent">
<% using (Html.BeginForm("MyAction", "MyController")) {%>
<%= Html.EditorFor(m => m.SomeString) %>
<%= Html.EditorFor(m => m.SomeDictionary["somevalue"]) %>
<input type="submit" value="Go" />
<%} %>
</asp:Content>
Run Code Online (Sandbox Code Playgroud)
作为参考,HTML输出是: …
拥有一个简单的 .NET Core API,并且模型在请求正文中以 JSON 形式发布,如何将[FromBody]属性应用于所有控制器方法?
[Route("api/simple")]
public class SimpleController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromBody] MyRequest request)
{
return Ok();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除该[FromBody]属性,所有模型属性都将为空。
首先,在这里忍受我.我有一个自定义模型绑定器,它成功地将表单数据映射到自定义对象.在此模型绑定器中,它还将表单项映射到不同的自定义对象.我觉得我应该做的是创建一个单独的模型绑定器来处理第二个映射.这是一个简化版本.
自定义对象:
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public string Description { get; set; }
public IEnumerable<SubCategory> SubCategories { get; set; }
}
public class SubCategory
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Status { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我的表单为SubCategories传回了一堆ID,那么我需要做的就是运行到数据存储库并为SubCategory对象加水.从表单中,将按以下格式提交子类别列表:
<input type="text" name="Name" value="This …Run Code Online (Sandbox Code Playgroud) 我有一个ViewModel,它包含以下结构:
public struct PricesAndDiscounts
{
public decimal FlatOff;
public decimal UnitPrice;
public decimal TotalDiscount;
public decimal TotalOptions;
public decimal TotalOrderPrice;
}
Run Code Online (Sandbox Code Playgroud)
ViewModel处于层次结构中,因此存在类型为PricesAndDiscounts的属性,该属性是DisplayRowPriceViewModel的成员,DisplayRowPriceViewModel是ManageOrderEditModel的成员:
-ManageOrderEditModel --DisplayRowPriceViewModel
.
请求的"形状"完全按照我的期望和期望(参见表单项的Fiddler截图):

但是,在服务器上,默认的模型绑定器将结构实例化为每个成员的零.ViewModel中的其他所有内容都是由ModelBinder创建的,没有任何问题.
我是否需要为自定义结构创建自定义ModelBinder?
编辑 - 添加更多详细信息
签名是:
public ActionResult ManageOrder([FromBody]ManageOrderEditModel model)
Run Code Online (Sandbox Code Playgroud)
我在没有FromBody属性的情况下尝试过它.此外,PriceAndDiscounts是一个结构的事实并不是问题.我把它改成了一个类,所有成员都以零的形式出现,而不是你从表单中看到的Fiddler中的值.
ManageOrderEditModel
public class ManageOrderEditModel
{
public DisplayOptionsInDropDownViewModel DisplayOptionsInDropDownViewModel { get; set; }
public DisplayRowPriceViewModel DisplayRowPriceViewModel { get; set; }
public int ID { get; set; }
public int RegType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
DisplayRowPriceViewModel
public class DisplayRowPriceViewModel
{
public Discount Discount { …Run Code Online (Sandbox Code Playgroud) 我有一个第三方应用程序向我的网站进行 POST 提交,正文中包含application/json 。我可以捕获强类型对象:
公共字符串回发([FromBody]MyResponse myResponse)
我的问题是,在完成这么多工作之后,我被指示在同一端点支持第二种类型。因此,我需要接受一个字符串值(而不是模型绑定器的结果),然后 JsonConvert 将该字符串转换为两种可能类型中的一种或另一种。
所以我想我应该将方法的签名更改为:
公共字符串回发([FromBody]字符串_sfResponse)
但该字符串始终显示为空(带或不带 [FromBody] 指令)。看来 ModelBinder 坚持要参与。无论如何要说服他不要这么做?
以防万一有关于路由的事情:
routes.MapRoute(
"MyPostback",
url: "rest/V1/sync/update",
defaults: new { controller = "Admin", action = "MyPostback" }
);
Run Code Online (Sandbox Code Playgroud)
控制器动作:
[System.Web.Mvc.HttpPost]
[System.Web.Mvc.AllowAnonymous]
public string MyPostback([System.Web.Http.FromBody][ModelBinder(typeof(MyResponseModelBinder))] MyResponseToProduct _sfResponse)
{
//stuff
}
Run Code Online (Sandbox Code Playgroud)
发送的 json 比平均值更复杂,但请记住,当控制器的签名引用与该 json 匹配的强类型对象时,一切正常。(重复一遍——我必须适应两种不同的传入类型,这就是为什么我需要在开头使用字符串而不是模型)。
{
"results": [
{
"errors": {
"error": "No Error"
},
"sku": "70BWUS193045G81",
"status": "success",
"productId": "123"
},
{
"errors": {
"error": "No Error"
},
"sku": "70BWUS193045G82",
"status": "success",
"productId": "123" …Run Code Online (Sandbox Code Playgroud)