asp.net-mvc-4 – 用于继承类型的WebApi模型绑定
|
我正在寻找在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调用? 解决方法以下是我在我的类型中继承的一个示例,并且在某些设置(如使用KnownType属性装饰,Xml格式化程序的datacontractserializer需要)和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:n{0}",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;
}
}
} (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc – ASP.NET MVC:通过两个控制器操作重用视图
- asp.net-mvc – 在ASP.NET MVC 4中的用户控制等效
- 如何在ASP.NET MVC控制器(ActionResult)中更改返回的Conten
- asp.net – page load()或者page init()
- asp.net – 直接将.aspx转换为.pdf [已关闭]
- asp.net-mvc-4 – 在MVC4环境中使用Razor和Angular.js
- asp.net-mvc – 使用@ Html.DisplayNameFor()与PagedList
- asp.net-mvc – 使用RadioButtons的可空值布尔的MVC3 Edito
- asp.net-mvc – Razor中()(括号)和{}(大括号)之间的差异
- 如何使用asp.net获取html select的所选值
- asp.net – 如何找到哪个控制器/操作发生错误?
- asp.net – 一些黑客可以从用户窃取cookie,并在网
- asp.net – “无法启动IIS Express Web服务器”错
- asp.net-web-api – 角色提供者/成员?如何在asp
- asp.net – WebForms中的Tabbing行为
- 过滤ASP.NET Core API中的属性
- 为什么要使用ASP.NET Membership安全模型?
- asp.net-core – CoreCLR中的哈希算法
- asp.net-mvc-3 – 如何增加会话超时MVC 3
- asp.net-mvc – MVC5 Html.RenderAction与不同的
