I have a Nancy.SelfHost service that is working just fine for the Get routes, but is failing on the Post route. If fails on the Bind<T>() command in the following route with a "No parameterless constructor defined for this object" error:
Post["/schedule"] = _ =>
{
var schedule = this.Bind<OatiDay[]>();
PostSchedule(schedule);
return HttpStatusCode.Created;
};
Here is the call stack returned with the error:
Nancy.RequestExecutionException: Oh noes! ---> System.MissingMethodException: No parameterless constructor defined for this object.
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at Nancy.Serialization.JsonNet.JsonNetBodyDeserializer.CreateObjectWithBlacklistExcluded(BindingContext context, Object deserializedObject)
at Nancy.Serialization.JsonNet.JsonNetBodyDeserializer.Deserialize(String contentType, Stream bodyStream, BindingContext context)
at Nancy.ModelBinding.DefaultBinder.DeserializeRequestBody(BindingContext context)
at Nancy.ModelBinding.DefaultBinder.Bind(NancyContext context, Type modelType, Object instance, BindingConfig configuration, String[] blackList)
at Nancy.ModelBinding.DynamicModelBinderAdapter.TryConvert(ConvertBinder binder, Object& result)
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at Nancy.ModelBinding.ModuleExtensions.Bind[TModel](INancyModule module)
at TSID.Scada.Nancy.ScheduleService.<.ctor>b__2(Object _) in p:\TSIDDev\TSID.Scada\TSID.Scada.Nancy\ScheduleService.cs:line 24
at CallSite.Target(Closure , CallSite , Func`2 , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Nancy.Routing.Route.<>c__DisplayClass4.<Wrap>b__3(Object parameters, CancellationToken context)
--- End of inner exception stack trace ---
at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)
It looks as though something is going wrong with the deserializer, but I can't tell what is being created. The post code is passing all its tests on the server using the Nancy Browser, so something must be wrong with the request. But I can't figure out what it is. The OatiDay class is just a poco object.
public class OatiDay
{
[BsonId]
public string Id { get; set; }
[BsonDateTimeOptions(DateOnly = true, Kind = DateTimeKind.Local)]
public DateTime Date { get; set; }
public String Facility { get; set; }
public Production OnPeak { get; set; }
public Production OffPeak { get; set; }
public class Production
{
public Int32 ScheduleForDay { get; set; }
public double? ActualForDay { get; set; }
public Int32 ScheduledToDate { get; set; }
public double? ActualToDate { get; set; }
}
}
Here is the request sent from an Angular $http service:
POST http://buckhorn1:7000/schedule HTTP/1.1
Host: buckhorn1:7000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Referer: http://buckhorn1:7203/schedule
Content-Length: 793
Origin: http://buckhorn1:7203
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
[{"id":"20150712","date":"2015-07-12T00:00:00Z","facility":"Watson","onPeak":{"scheduleForDay":0,"actualForDay":6.56,"scheduledToDate":77,"actualToDate":92.61},"offPeak":{"scheduleForDay":12,"actualForDay":4.26,"scheduledToDate":71,"actualToDate":64.97},"hasPeak":false},{"id":"20150713","date":"2015-07-13T00:00:00Z","facility":"Watson","onPeak":{"scheduleForDay":8,"actualForDay":8,"scheduledToDate":85,"actualToDate":100.61},"offPeak":{"scheduleForDay":4,"actualForDay":4,"scheduledToDate":75,"actualToDate":68.97},"hasPeak":true},{"id":"","date":"2015-07-14T00:00:00.000Z","facility":"Watson","hasPeak":true,"onPeak":{"scheduleForDay":9,"scheduledToDate":94,"actualForDay":9,"actualToDate":109.61},"offPeak":{"scheduleForDay":5,"scheduledToDate":80,"actualForDay":5,"actualToDate":73.97}}]
Can anyone tell me how to troubleshoot this?
I could not get the Nancy model-binding to work. I suspected it had something to do with the deserialization of the camel cased body. I replaced this:
var schedule = this.Bind<OatiDay[]>();
with this:
var reader = new StreamReader(this.Request.Body);
string text = reader.ReadToEnd();
var schedule = JsonConvert.DeserializeObject<OatiDay[]>(text);
and my service is working.