65.9K
CodeProject 正在变化。 阅读更多。
Home

MVC 中的自定义格式化程序和数据绑定

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (5投票s)

2016 年 10 月 31 日

CPOL

2分钟阅读

viewsIcon

11996

MVC 中的自定义格式化程序和数据绑定

引言

本文的目的是解决在 MVC 应用程序中处理自定义数据绑定的场景。我们知道,数据绑定和请求/响应处理是 MVC 框架的关键可扩展点之一。

自定义格式化程序

让我们从自定义格式化程序开始。当我们需要发送/获取除 JSON 或 XML 以外的数据结构时,这非常有用。我们知道 MVC 默认支持这两种数据编码方案。另一种解决问题的方法只是在发送到 API 之前准备好数据的 XML 或 JSON 格式。但更好的解决方案是编写自定义格式化程序并将其挂接到 MVC 框架中。假设我们有一些逗号分隔的信息,想要将其提供给 API。在这个例子中,我们将看到如何使用自定义格式化程序处理这样的值。这是我们最简单的 DTO 类。

	public class Person
    {
        public string Name { get; set; }
        public string Surname { get; set; }
    }

现在我们创建了从“BufferedMediaTypeFormatter”派生的 CommaFormatter。构造函数中选择了 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<Person>))
                return true;
            else
                return false;
        }
        public override bool CanWriteType(Type type)
        {
            if (type == typeof(Person) || type == typeof(List<Person>))
                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 模型来演示这个例子。

	public class Person
    {
        public string Name { get; set; }
        public string Surname { get; set; }
    }

我们创建了从 DefaultModelBinder 派生并重写 BindModel 方法的 PersonModelBinder。在这个方法中,我们从请求上下文中获取查询字符串的值,并将其作为 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)
        {
           
        }
    }

我们看到该值已绑定到操作中。

结论:在这两个例子中,我们看到了如何在 MVC 中处理自定义数据格式。当您不想在发送到 API 之前将数据转换为 XML 或 JSON 时,格式化程序很有用,而自定义模型绑定器适用于数据量小且足以作为查询字符串传递的情况。

© . All rights reserved.