创建需要类型信息的 MVC3 ValueProviderFactories?

发布于 2024-11-27 06:39:39 字数 669 浏览 0 评论 0原文

我正在尝试为 ASP MVC3 编写 Protobuf ValueProviderFactory。我已经设法弄清楚如何添加工厂,但是现在我偶然发现了一个更紧迫的问题。 这是当前序列化发生在 JsonValueProviderFactory.cs 中的位置

    JavaScriptSerializer serializer = new JavaScriptSerializer();
    object jsonData = serializer.DeserializeObject(bodyText);
    return jsonData;

那么反序列化是在没有任何类型信息的情况下完成的吗? DeserializeObject 返回什么类型的对象?动态?它如何知道数据的类型?我希望将 protobuf-net 放在这里,但它显然需要一种类型来发挥它的魔力!

我没有查看所有 MVC3 源代码,但我猜测到类型的映射发生在最后阶段,并且无法知道 ValueProviderFactories 中的类型?

我是否必须放弃并在行动上进行转换?

I'm attempting to write a Protobuf ValueProviderFactory for ASP MVC3. I've managed to work out how to add the factories, but now I've stumbled on a more pressing problem.
Here is where the current serialization takes place in JsonValueProviderFactory.cs

    JavaScriptSerializer serializer = new JavaScriptSerializer();
    object jsonData = serializer.DeserializeObject(bodyText);
    return jsonData;

So the deserialization is accomplished without any type information? What sort of object does DeserializeObject return? A Dynamic? How does it know the type of data? I was hoping to slot protobuf-net in here but it obviously needs a type to do its magic!

I haven't looked through all the MVC3 source, but I'm guessing the mapping to types occurs at the final stage, and there is no way to know of the types in the ValueProviderFactories?

Will I have to give up and do the conversion in the actions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

臻嫒无言 2024-12-04 06:39:39

这里有几个问题。

有关 JavaScriptSerializer 的工作原理,您应该阅读 文档。该类尝试推断基本类型(int、bool、date 等)的类型,并针对更复杂的情况返回 Dictionary。此外,如果 JSON blob 包含名为“__type”的特殊属性,则反序列化器将尝试创建该类型的对象。

现在介绍一下 MVC 中的工作原理。将请求中的值映射到控制器中使用的对象实例的过程称为模型绑定。它分为两个组件:ModelBinder 和 ValueProviders。模型绑定器知道目标类型(例如产品),尝试创建它的实例,然后使用请求中的值填充其属性。它通过询问 ValueProviders 来实现这一点。例如,要在 Product 实例上设置 Name 属性,它会向值提供者询问“Name”的值。值提供者按顺序查询并返回匹配项(来自查询字符串、发布数据、JSON 请求正文等)。

网络上有很多关于这方面的资源,但简而言之,价值提供者不应该真正关心类型。

There are a few questions here.

For how JavaScriptSerializer works you should read the documentation. The class tries to infer the type for basic types (int, bool, date, etc) and returns Dictionary<string, object> for more complex cases. In addition if the JSON blob contains a special property called "__type" then the deserializer will try to create an object of that type.

Now for how this works in MVC. The process of mapping values from a request to an object instance used in your controller is called model binding. This is split into two components: ModelBinder and ValueProviders. The model binder knows the target type (e.g. Product), tries to create an instance of it, and then populate its properties with values from the request. It does so by asking the ValueProviders. For example, to set the Name property on the Product instance it asks the value providers for the value of "Name". The value providers get queried in sequence and return a match (from query string, post data, JSON request body, etc).

There's lots of resources about this on the web, but in short value providers shouldn't really be concerned with types.

长伴 2024-12-04 06:39:39

下面是 marcind 建议的使用 ModelBinder 的解决方案的快速尝试。它尚未经过测试,但它是一个开始。在本例中,FromProtobuf 是一个简单的 byte[] 到对象扩展方法。

public class ProtobufModelBinder<T> : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/x-protobuf", StringComparison.OrdinalIgnoreCase))
            return null;

        using (MemoryStream ms = new MemoryStream())
        {
            controllerContext.HttpContext.Request.InputStream.CopyTo(ms);
            return ms.ToArray().FromProtobuf<T>();
        }
    }
}

可以按如下方式设置:

ModelBinders.Binders.Add(typeof(MyClass), new ProtobufModelBinder<MyClass>());

Here is a quick stab at a solution using a ModelBinder, as suggested by marcind. It's untested, but it's a start. In this case FromProtobuf<T> is a simple byte[] to object extension method.

public class ProtobufModelBinder<T> : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/x-protobuf", StringComparison.OrdinalIgnoreCase))
            return null;

        using (MemoryStream ms = new MemoryStream())
        {
            controllerContext.HttpContext.Request.InputStream.CopyTo(ms);
            return ms.ToArray().FromProtobuf<T>();
        }
    }
}

This could be setup as follows:

ModelBinders.Binders.Add(typeof(MyClass), new ProtobufModelBinder<MyClass>());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文