在MVC框架中,数据绑定和请求/响应处理是框架的关键可扩展点之一。本文将介绍如何在MVC应用中实现自定义数据格式的绑定和处理。
自定义格式化器非常有用,尤其是当需要发送或接收JSON或XML以外的数据结构时。虽然MVC默认支持这两种数据编码方案,但更好的解决方案可能是编写自定义格式化器并将其集成到MVC框架中。例如,如果有一些逗号分隔的信息想要传递给API,将展示如何使用自定义格式化器处理这样的值。
首先,定义了一个简单的数据传输对象(DTO)类:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}
接下来,创建了一个名为CommaFormatter
的类,它继承自BufferedMediaTypeFormatter
。在构造函数中,选择了MIME类型:
public class CommaFormatter : BufferedMediaTypeFormatter
{
public CommaFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/colon"));
}
public override bool CanReadType(Type type)
{
if (type == typeof(Person) || type == typeof(List))
return true;
else
return false;
}
public override bool CanWriteType(Type type)
{
if (type == typeof(Person) || type == typeof(List))
return true;
else
return false;
}
public override object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
List<Person> Obj = new List<Person>();
Person p = null;
StreamReader reader = new StreamReader(readStream);
string str = reader.ReadToEnd();
string[] propArr = str.Split(',');
foreach (var item in propArr)
{
string[] propAttribute = item.Split('|');
p = new Person();
foreach (var item1 in propAttribute)
{
string[] propAttribute1 = item1.Split('=');
if (propAttribute1[0].ToLower().Trim().Equals("name"))
{
p.Name = propAttribute1[1];
}
if (propAttribute1[0].ToLower().Trim().Equals("surname"))
{
p.Surname = propAttribute1[1];
}
}
Obj.Add(p);
}
return Obj;
}
}
现在,需要在全局配置页面中注册这个格式化器,以便它在MVC中被注册:
GlobalConfiguration.Configuration.Formatters.Add(new CommaFormatter());
在API的Post
方法中,尝试传递“Person”列表:
public class CustomController : ApiController
{
[HttpPost]
public void Post(List<Person> p)
{
}
}
请确保在请求头中设置了“Content-Type”。可以观察到,负载是自定义的数据格式,并且绑定到动作方法。
这是另一种将未格式化数据绑定到MVC端点的方法。想象一下,数据来自查询字符串的场景。知道,如果查询字符串的键与模型属性匹配,MVC默认能够智能绑定。但如果查询字符串与模型属性不匹配呢?自定义模型绑定器就派上用场了。用一个简单的“Person”模型来演示这个例子。
创建了一个名为PersonModelBinder
的类,它继承自DefaultModelBinder
并覆盖了BindModel
方法。在这个方法中,从请求上下文中获取查询字符串的值,并将其作为Person模型的具体对象返回:
public class PersonModelBinder : DefaultModelBinder
{
public PersonModelBinder()
{
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
string name = request.QueryString["name"];
string surname = request.QueryString["surname"];
return new Person { Name = name, Surname = surname };
}
}
以下是将自定义格式化器集成到MVC管道中的步骤:
ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder());
为了将数据作为参数接收,必须使用ModelBinder
属性:
public class CustomController : Controller
{
public void Post([ModelBinder(typeof(PersonModelBinder))] Person p)
{
}
}