9

In Nancy, is there a way to bind the content of a POST request to a dynamic type?

For example:.

// sample POST data: { "Name": "TestName", "Value": "TestValue" }

// model class
public class MyClass {
    public string Name { get; set; }
    public string Value { get; set; }
}

// NancyFx POST url
Post["/apiurl"] = p => {

    // this binding works just fine
    var stronglyTypedModel = this.Bind<MyClass>();

    // the following bindings do not work
    // there are no 'Name' or 'Value' properties on the resulting object
    dynamic dynamicModel1 = this.Bind();
    var dynamicModel2 = this.Bind<dynamic>();
    ExpandoObject dynamicModel3 = this.Bind();
    var dynamicModel4 = this.Bind<ExpandoObject>();

}
4

4 回答 4

11

开箱即用的 Nancy 不支持动态模型绑定。TheCodeJunkie 编写了一个快速的 ModelBinder 来实现这一点。

https://gist.github.com/thecodejunkie/5521941

然后你可以像这样使用它

dynamic model = this.Bind<DynamicDictionary>();

于 2013-05-24T03:14:36.517 回答
2

正如前面的答案所指出的,不支持直接绑定到动态类型,最相似的是TheCodeJunkie在https://gist.github.com/thecodejunkie/5521941提供的ModelBinder

但是,这种方法有一个问题,即由此代码生成的 DynamicDictionary 稍后无法正确序列化,仅生成字典的键并丢失值。此处描述了为什么在 RavenDB 中存储 Nancy.DynamicDictionary 仅保存属性名称而不保存属性值?直到今天(1.4.3 版)仍在发生,严重限制了这种方法。

解决方案是使用一个简单的技巧,访问 POST 中收到的原始数据并使用 JSON.Net 进行反序列化。在您的示例中,它将是:

using System;
using System.Dynamic;
using Nancy;
using Nancy.Extensions;
using Newtonsoft.Json;

Post["/apiurl"] = p => {
    dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(Request.Body.AsString());

    //Now you can access the object using its properties
    return Response.AsJson((object)new { a = obj.Prop1 });
}

请注意,您需要对 Request.Body.AsString() 调用使用 Nancy.Extensions。

于 2016-09-11T15:24:35.627 回答
0

我正在寻找一种方法将我的 POST 正文反序列化为动态并发现这个问题,我将使用 Newtonsoft 和扩展方法放置我的解决方案,以防万一结果对其他人有用。

扩展方法

using System.IO;
using Nancy;
using Newtonsoft.Json;

namespace NancyFx
{
    public static class DynamicModelBinder
    {
        public static dynamic ToDynamic(this NancyContext context)
        {
            var serializer = new JsonSerializer();
            using (var sr = new StreamReader(context.Request.Body))
            {
                using (var jsonTextReader = new JsonTextReader(sr))
                {
                    return serializer.Deserialize(jsonTextReader);
                }
            }
        }
    }
}

用法

using Nancy;
using Nancy.ModelBinding;

namespace NancyFx
{
    public class HomeModule : NancyModule
    {
        public HomeModule(IAppConfiguration appConfig)
        {
            Post("/product", args => {
                dynamic product = Context.ToDynamic();
                string name = product.Name;
                decimal price = product.Price;
                return Response.AsJson(new {IsValid=true, Message= "Product added sucessfully", Data = new {name, price} });
            });
        }
    }
}
于 2017-10-19T21:30:51.747 回答
-1

我不确定,但您可以尝试:

dynamic model = new ExpandoObject();
model = Request; //or Request.Form
return View["ViewName", model];

让我知道是否有效:)

于 2013-05-23T23:22:33.410 回答