rest - ServiceStack deserialization of JSON content in multipart/form-data request -


i'm creating restful service using servicestack should consume post multipart/form-data content. content in json format, when send post, object not deserialized correctly (all properties null/default values). if try sending object regular post (without multipart/form-data), deserializes fine.

i poked around in servicestack code try figure out going on, , current understanding:

  • httplistenerrequestwrapper::loadmultipart() loading multipart request , saving (non-file) parts "formdata", maps name of part contents. however, appears content-type (which correctly written httpmultipart::element individual sections being parsed) lost because isn't stored in anywhere.
  • some time later in control-flow, endpointhandlerbase::deserializehttprequest() calls keyvaluedatacontractdeserializer.instance.parse() formdata , type deserialize to.
  • if first time kind of object being deserialized, stringmaptypedeserializer created type , cached typestringmapserializermap. each property of type, call jsvreader.getparsefn() parsestringdelegate parse deserialize property.
  • the created/cached stringmaptypedeserializer used deserialize object, using "parsefn's" set earlier... treat content jsv format.

i confirmed jsvreader.parsefncache has bunch of types in it, while jsonreader.parsefncache empty. also, if change request remove quotes (i.e. turn json jsv format), deserializes correctly. 1 weird thing 1 of properties of object dictionary, , deserializes correctly, when it's in json format; i'm assuming fortunate coincidence (?!?).

am correct in understanding of what's going on here? known limitation in servicestack? bug? there anyway work around other putting object in file , manually calling jsonserializer.deserializefromstream()?

thanks!

jps

also, incase it's useful, here's relevant request , data-objects:

post /api/task http/1.1 accept: application/json content-type: multipart/form-data; boundary=boundary_1_1161035867_1375890821794 mime-version: 1.0 host: localhost:12345 content-length: 385  --boundary_1_1161035867_1375890821794 content-type: application/json content-disposition: form-data; name="mymap"  {"myfile.dat":"importantfile"} --boundary_1_1161035867_1375890821794 content-disposition: form-data; name="mything" content-type: application/json  {"id":123,"name":"myteststring"} --boundary_1_1161035867_1375890821794 content-type: application/octet-stream content-disposition: form-data; filename="myfile.dat"  mydatagoeshere... --boundary_1_1161035867_1375890821794-- 

.

public class testobj {     public long id { get; set; }     public string name { get; set; } }  [route("/task", "post")] public class taskrequest : authenticatedrequest, ireturn<taskresponse> {     public testobj mything { get; set; }     public dictionary<string, string> mymap { get; set; } } 

have tried setting properties of request object using 'apimember' attribute? in particular 'parametertype' properties.

/// <summary> /// create , upload new video. /// </summary> [api("create , upload new video.")] [route("/videos", "post", summary = @"create , upload new video.",     notes = "video file / attachment must uploaded using post , 'multipart/form-data' encoding.")] public class createvideo : operationbase<ivideo> {     /// <summary>     /// gets or sets video title.     /// </summary>     [apimember(name = "title",         allowmultiple = false,         datatype = "string",         description = "video title. required, between 8 , 128 characters.",         isrequired = true,         parametertype = "form")]     public string title { get; set; }      /// <summary>     /// gets or sets video description.     /// </summary>     [apimember(name = "description",         allowmultiple = false,         datatype = "string",         description = "video description.",         parametertype = "form")]     public string description { get; set; }      /// <summary>     /// gets or sets publish date.     /// </summary>     /// <remarks>     /// if blank, video published immediately.     /// </remarks>     [apimember(name = "publishdate",         allowmultiple = false,         datatype = "date",         description = "publish date. if blank, video published immediately.",         parametertype = "form")]     public datetime? publishdate { get; set; } } 

Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

.htaccess - Matching full URL in RewriteCond -