2013-05-23 4 views
8

В Нэнси существует ли способ связать содержимое запроса POST с динамическим типом?NancyFx привязывает модель к динамическому типу?

Например:.

// 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>(); 

} 
+1

Разве вы не можете просто сделать пост [ "/ apiurl"] = р => {динамическая модель = р; string name = model.Name; string val = model.Value; }? – Alexander

+0

@Alexander, PLS сообщение u'r комментарий, как ответ, чтобы получить репутацию, когда это происходит :) –

+0

Спасибо за ответ Alexander. 'p' уже является динамическим типом, но я не могу получить доступ к данным в теле запроса, потому что его нужно сначала десериализовать. Если бы это была строка запроса или параметр маршрута, я мог бы получить доступ к нему из «p», но в этом случае мне нужно десериализовать данные JSON из тела запроса. – user326502

ответ

9

Из коробки Нэнси не поддерживает динамическую модель связывания. TheCodeJunkie написал быстрый ModelBinder для достижения этой цели.

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

Затем вы можете использовать его как так

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

+0

Ты избил меня до этого;) – TheCodeJunkie

+0

Спасибо, ребята. Я скопировал и модифицировал по умолчанию модельное связующее в соответствии с моими потребностями, но связующее вещество CodeJunkie намного чище. :) – user326502

+0

@ user326502: можете ли вы поделиться своим решением, чтобы заставить его модельный блок работать с действиями POST? –

-1

Я не уверен, но вы можете попробовать:

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

дайте мне знать, если работает :)

1

В предыдущем пункте ответов, нет никакой поддержки для привязки непосредственно к динамическому типу, наиболее похожий один является ModelBinder предоставленный TheCodeJunkie в https://gist.github.com/thecodejunkie/5521941

Однако этот подход имеет проблему и заключается в том, что DynamicDictionary, являющийся результатом этого кода, не является rialize позже правильно, производя только ключи словаря и теряя значения. Это описано здесь Why does storing a Nancy.DynamicDictionary in RavenDB only save the property-names and not the property-values? и на сегодняшний день (версия 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 }); 
} 

Обратите внимание, что вам нужно использовать Nancy.Extensions для вызова Request.Body.AsString().

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} }); 
      }); 
     } 
    } 
} 
Смежные вопросы