关键词:
【中文标题】继承类型的 WebApi 模型绑定【英文标题】:WebApi Model Binding For Inherited Types 【发布时间】:2013-03-09 01:37:45 【问题描述】:我希望在 WebApi 中处理继承类型的模型绑定,而我真正想做的是使用默认模型绑定来处理绑定(除了选择无法这样做的类型) ,但我缺少一些基本的东西。
所以说我有类型:
public abstract class ModuleVM
public abstract ModuleType ModuleType get;
public class ConcreteVM : ModuleVM
使用 MVC 控制器,我会做这样的事情:
public class ModuleMvcBinder : DefaultModelBinder
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
if (modelType == typeof(ModuleVM))
// Just hardcoding the type for simplicity
Type instantiationType = typeof(ConcreteVM);
var obj = Activator.CreateInstance(instantiationType);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
bindingContext.ModelMetadata.Model = obj;
return obj;
return base.CreateModel(controllerContext, bindingContext, modelType);
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Struct | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class ModuleMvcBinderAttribute : CustomModelBinderAttribute
public override IModelBinder GetBinder()
return new ModuleMvcBinder();
然后使用控制器上的属性,一切都很好,我正在利用 DefaultModelBinder 进行实际工作,我基本上只是提供正确的对象实例化。
那么我该如何为 WebApi 版本做同样的事情呢?
如果我使用自定义模型绑定器(例如Error implementing a Custom Model Binder in Asp.Net Web API),我的问题是(我相信)在 BindModel 方法中,一旦实例化对象,我还没有找到使用“标准”http 绑定的好方法.正如其他帖子中所建议的那样,我可以专门针对 JSON (Deserialising Json to derived types in Asp.Net Web API) 或 XML (Getting my Custom Model bound to my POST controller) 执行此操作,但在我看来,这违背了这一点,因为 web api 应该将其分开,而且是 - 它只是没有知道如何确定类型。 (所有具体类型自然都处理得很好。)
我是否忽略了一些明显的事情,我应该在实例化对象后将 BindModel 调用定向到?
【问题讨论】:
你找到解决办法了吗? 【参考方案1】:以下是一个示例,其中我的类型具有继承性,并且在进行了一些设置(例如使用 Xml 格式化程序的 datacontractserializer 所需的 KnownType 属性进行装饰)和 Json 格式化程序上的 TypeNameHandling 设置之后,我们可以预期两个 xml/json 请求的行为一致。
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using System.Web.Http;
using System.Web.Http.SelfHost;
namespace Service
class Service
private static HttpSelfHostServer server = null;
private static string baseAddress = string.Format("http://0:9095/", Environment.MachineName);
static void Main(string[] args)
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(baseAddress);
config.Routes.MapHttpRoute("Default", "api/controller/id", new id = RouteParameter.Optional );
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
try
server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
Console.WriteLine("Service listenting at: 0 ...", baseAddress);
TestWithHttpClient("application/xml");
TestWithHttpClient("application/json");
Console.ReadLine();
catch (Exception ex)
Console.WriteLine("Exception Details:\n0", ex.ToString());
finally
if (server != null)
server.CloseAsync().Wait();
private static void TestWithHttpClient(string mediaType)
HttpClient client = new HttpClient();
MediaTypeFormatter formatter = null;
// NOTE: following any settings on the following formatters should match
// to the settings that the service's formatters have.
if (mediaType == "application/xml")
formatter = new XmlMediaTypeFormatter();
else if (mediaType == "application/json")
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
formatter = jsonFormatter;
HttpRequestMessage request = new HttpRequestMessage();
request.RequestUri = new Uri(baseAddress + "api/students");
request.Method = HttpMethod.Get;
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType));
HttpResponseMessage response = client.SendAsync(request).Result;
Student std = response.Content.ReadAsAsync<Student>().Result;
Console.WriteLine("GET data in '0' format", mediaType);
if (StudentsController.CONSTANT_STUDENT.Equals(std))
Console.WriteLine("both are equal");
client = new HttpClient();
request = new HttpRequestMessage();
request.RequestUri = new Uri(baseAddress + "api/students");
request.Method = HttpMethod.Post;
request.Content = new ObjectContent<Person>(StudentsController.CONSTANT_STUDENT, formatter);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType));
Student std1 = client.SendAsync(request).Result.Content.ReadAsAsync<Student>().Result;
Console.WriteLine("POST and receive data in '0' format", mediaType);
if (StudentsController.CONSTANT_STUDENT.Equals(std1))
Console.WriteLine("both are equal");
public class StudentsController : ApiController
public static readonly Student CONSTANT_STUDENT = new Student() Id = 1, Name = "John", EnrolledCourses = new List<string>() "maths", "physics" ;
public Person Get()
return CONSTANT_STUDENT;
// NOTE: specifying FromBody here is not required. By default complextypes are bound
// by formatters which read the body
public Person Post([FromBody] Person person)
if (!ModelState.IsValid)
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState));
return person;
[DataContract]
[KnownType(typeof(Student))]
public abstract class Person : IEquatable<Person>
[DataMember]
public int Id get; set;
[DataMember]
public string Name get; set;
public bool Equals(Person other)
if (other == null)
return false;
if (ReferenceEquals(this, other))
return true;
if (this.Id != other.Id)
return false;
if (this.Name != other.Name)
return false;
return true;
[DataContract]
public class Student : Person, IEquatable<Student>
[DataMember]
public List<string> EnrolledCourses get; set;
public bool Equals(Student other)
if (!base.Equals(other))
return false;
if (this.EnrolledCourses == null && other.EnrolledCourses == null)
return true;
if ((this.EnrolledCourses == null && other.EnrolledCourses != null) ||
(this.EnrolledCourses != null && other.EnrolledCourses == null))
return false;
if (this.EnrolledCourses.Count != other.EnrolledCourses.Count)
return false;
for (int i = 0; i < this.EnrolledCourses.Count; i++)
if (this.EnrolledCourses[i] != other.EnrolledCourses[i])
return false;
return true;
【讨论】:
欣赏它 Kiran,这绝对是有用的代码。最终,虽然您不是使用 xml 和 json 序列化而不是模型绑定器吗? (Json 通过类型信息,很遗憾我无法添加,xml 通过 DataContract 属性。)我真的很想使用模型绑定器,因为我最终将无法装饰所有类型并且不能需要 JSON 上的类型信息。复杂抽象对象的WebAPI自定义模型绑定
...试以多态方式解析提供的记录,并提供它将解析到的记录类型(我希望将来能够添加许多记录类型)。我尝试在调用端点时使用followingexample来解析我的模型,但是 查看详情
WebAPI:HttpClient 响应字符串模型绑定
...2:45:29【问题描述】:如何将WebApi的json/xml响应绑定到模型类型?就像我有一个模型用户并且我的api以json/xml格式返回用户列表,那么我怎样才能自动将响应绑定到List<users>?在带有WebHttpB 查看详情
webapi模型绑定一(代码片段)
...api/?view=aspnetcore-2.2]1.模型绑定 简单模型绑定针对简单类型(如string,int,DateTime等)可进行单一绑定;但若遇到复杂类型,则需要通过反射和递归遍历查找,查找模式paramter_name.property_name。 >>>对于 查看详情
来自 JSON 的 WebAPI 模型绑定
】来自JSON的WebAPI模型绑定【英文标题】:WebAPIModelBindingfromJSON【发布时间】:2013-04-2820:58:11【问题描述】:我正在使用Durandal创建一个应用程序,并将WebAPI作为服务器。我有一个KendoUI网格,可以正确显示来自服务器的数据并正常... 查看详情
C# webAPI 无法将原始整数值绑定到正文中的模型?
】C#webAPI无法将原始整数值绑定到正文中的模型?【英文标题】:C#webAPIcannotbindoriginalintegervaluetomodelfromthebody?【发布时间】:2020-11-1013:18:36【问题描述】:我的问题是,当我将有效负载正文中以零(012345)开头的任何整数值发送到C#... 查看详情
模型绑定不适用于 ASP.NET Core 2 WebAPI 中的 POST 请求
】模型绑定不适用于ASP.NETCore2WebAPI中的POST请求【英文标题】:ModelbindingisnotworkingonPOSTrequestinASP.NETCore2WebAPI【发布时间】:2018-03-2700:09:39【问题描述】:这是我的模型。publicclassPatientpublicstringNameget;set;publicstringGenderget;set;publicdouble... 查看详情
MVC4 webapi中的反序列化/模型绑定不适用于数组
】MVC4webapi中的反序列化/模型绑定不适用于数组【英文标题】:Deserialization/modelbindinginMVC4webapidoesnotworkwitharrays【发布时间】:2012-03-2411:18:02【问题描述】:我正在使用新的WebApi,它是MVC4测试版的一部分。我有以下课程:publicclass... 查看详情
为啥我的多态类型是我的模型继承的类?
】为啥我的多态类型是我的模型继承的类?【英文标题】:Whyismypolymorphictypetheclassthatmymodelinheritsfrom?为什么我的多态类型是我的模型继承的类?【发布时间】:2018-11-2103:21:09【问题描述】:我有一个继承自其他基础模型的模型:... 查看详情
如何传递 WebAPI 控制器数据,以便发布模型在绑定/反序列化或验证时可以访问
】如何传递WebAPI控制器数据,以便发布模型在绑定/反序列化或验证时可以访问【英文标题】:HowtopassWebAPIControllerdatasuchthatPostedModelhasaccessatBinding/DeserializationorValidationTime【发布时间】:2020-01-2802:51:52【问题描述】:考虑这个WebAPI... 查看详情
为啥事件不支持绑定继承类型?
】为啥事件不支持绑定继承类型?【英文标题】:Whyeventsdoesnotsupportbindinginheritedtypes?为什么事件不支持绑定继承类型?【发布时间】:2011-07-2112:19:57【问题描述】:在这些代表中:EventHandlerpublicdelegatevoidEventHandler(objectsender,EventAr... 查看详情
day33序列类型,绑定方法,类方法,静态方法,封装继承和多态
...Day20= 序列类型,绑定方法,类方法,静态方法,封装继承和多态 序列是指有序的队列,重点在"有序"。一、Python中序列的分类Python中的序列主要以下几种类型:3种基本序列类型(BasicSequenceTypes):list、tuple、range专门处理... 查看详情
模型绑定
...型绑定器数据检测顺序: 1、检测目标对象的名称和类型。通常是动作方法的参数。 2、通过已知对象查找数据源(http请求),并找到可用数据(字符串值)。 3、根据对象的类型把可用数据值转换为目标类型。如果转换... 查看详情
java继承
...就确定好如何调用动态绑定:运行时才确定如何调用,有继承关系的话会看对象的实际类型,决定该调用什么方法子类覆盖父类的方法,需要保证返回类型是父类方法返回类型的子类型final修饰类可以防止其被继承,修饰类中的... 查看详情
泛型类型的自定义模型绑定
】泛型类型的自定义模型绑定【英文标题】:Custommodelbindingforgenerictype【发布时间】:2019-12-0721:02:42【问题描述】:我有一个ASP.NetMVC4应用程序,我正在尝试创建自定义模型绑定器。它必须处理的模型是这样的:publicclassCompressedJs... 查看详情
模型绑定自定义类型
】模型绑定自定义类型【英文标题】:ModelBindingCustomType【发布时间】:2011-02-0810:00:53【问题描述】:我有一个很像System.Nullable类型的结构:publicstructSpecialProperty<T>publicstaticimplicitoperatorT(SpecialProperty<T>value)returnvalue.Value;pu... 查看详情
模型绑定
...on方法里。这些参数可以是string、interger、float这样的简单类型,也可以是复杂类型。这是MVC一个非常棒的功能,因为无论传入数据的大小或复杂性如何,映射传 查看详情
Web API 无法使用 utf-16 编码的 XML 绑定 POST 模型
】WebAPI无法使用utf-16编码的XML绑定POST模型【英文标题】:WebAPInotabletobindmodelforPOSTwithutf-16encodedXML【发布时间】:2017-02-1614:31:40【问题描述】:我有一个带有POST方法的简单WebAPI控制器,它接受一个对象。当客户端将数据发布为JSON... 查看详情
.net core 模型绑定类型转换错误
】.netcore模型绑定类型转换错误【英文标题】:.netcoremodelbindingtypeconversionerrors【发布时间】:2022-01-0611:11:04【问题描述】:我有一个.net核心应用程序。一些端点有一些模型,模型中的一些属性有int类型。如果用户传递字符串而... 查看详情