Can't parse JSON parameter - json

I am using WebAPI to get the POST message. The body of the POST message:
{"datetime":"2017-01-06T20:40:44.2401244Z","filename":"somefilename.csv","datasourcename":"MyDataSource","error":"The uploaded file has no tags."}
The header included with the POST:
Content-type: application/json
My action method that handle the message:
[HttpPost]
public void SaveMessage([FromBody] string msg)
{
MyModel w = JsonConvert.DeserializeObject<MyModel>(msg);
db.MyModels.Add(w);
db.SaveChanges();
}
My question is how do I encode the JSON so that I can parse it? I can't change the incoming message. What can I do in my method so that I can read it? Right now msg always give me null.

Given that you have no control over the data being sent, then as suggested in the comments, make sure you have a model that matches the desired object model of the JSON
public class MyModel {
public DateTime datetime { get; set; }
public string filename { get; set; }
public string datasourcename { get; set; }
public string error { get; set; }
}
And take advantage of the model binding capability of the Web API framework and let the action bind a strongly typed model from the body of the request.
[HttpPost]
public IHttpActionResult SaveMessage([FromBody] MyModel model) {
if(ModelState.IsValid) {
db.MyModels.Add(w);
if(db.SaveChanges() > 0)
return Ok();
}
return BadRequest();
}
If there are any issues with saving the message the action will return HTTP Status Code 400 Bad Request, otherwise it will return HTTP Status Code 200 OK.

Related

Custom serialization in Service Stack using DeSerializeFn

In servicestack, I am trying to process a webhook which sends the following JSON body to a service stack endpoint:
{
"action": "actionType1",
"api_version": "1.00",
"data": {
"id": "a8d316b8-10a7-4440-a836-9bd354f656db",
//VARIABLE other properties / structure
}
}
Which I am trying to map to the following request object:
[Route("/public/Webhookhandler", HttpVerbs.Post)]
public class MyCustomRequst
{
public string action { get; set; }
public string api_version { get; set; }
public string data { get; set; } //Will be the remaining JSON
}
However, when the service stack framework processes this - the value in "data" is the correct part of the JSON body, but with all of the quotes removed - so it is no longer valid.
I have tried to override the serialization for the whole request object using something like this:
JsConfig<MyCustomRequst>.DeSerializeFn = DeserializeMyRequestDto;
public MyCustomRequst DeserializeMyRequestDto(string rawBody)
{
var result = rawBody.FromJson<MyCustomRequst>();
return result
}
But even in this case, the value of the "rawBody" variable is still the correct JSON data but with all the quotes removed, e.g.
{
action:actionType1,
api_version:1.00,
data:{id:a8d316b8-10a7-4440-a836-9bd354f656db}
}
Am I doing something wrong here? I am unsure whether I am trying to make service stack do something it is not intended to do, or whether I am missing something that would make this work.
Any help would be appreciated :-)
Your DTO should closely match the shape of the JSON, if it's always a flat object you can use a string Dictionary, e.g:
[Route("/public/Webhookhandler", HttpVerbs.Post)]
public class MyCustomRequst
{
public string action { get; set; }
public string api_version { get; set; }
public Dictionary<string,string> data { get; set; }
}
If it's a more nested object structure you can use a JsonObject for a more flexible API to parse dynamically.

How to pass multiple json value for post method using fiddler

I'm new with web api and fiddler as well as json, i want to test my api with fiddler.
In this image i've recieved the requested data
and I've returned Json data to mobile device but now when i want to test it through fiddler web debugger
it shows "HTTP/1.1 404 Not Found" in fiddler Headers tab
What you need is a method that takes as a parameter the object sent as JSON. WebApi will handle the deserialization for you.
Something like this on server side would work:
public class BooksController : ApiController
{
[HttpPost]
public void Post([FromBody]Book book)
{
// do someting with book here...
}
}
public class Book
{
public string OfficeCode { get; set; }
public string BookNo { get; set; }
public string MeterNo { get; set; }
public string AccountNo { get; set; }
}
From the client, the body should look like
{
"OfficeCode": "string",
"BookNo": "string",
"MeterNo": "string",
"AccountNo": "string"
}
I think you are forgetting method name.
Give full URL as below:
http://localhost:9090/api/ReadingBook/PostCustomerBills
Also I can see that you haven't specified [HttpPost] on PostCustomerBills method.

Unable to retrieve Json data from remote server binding to object in asp.net mvc

I am developing an Asp.Net mvc application. In my application, I need to retrieve json object from remote server. I am using web client for it. But it is giving me error. My scenario is below.
I have this url
http://graph.facebook.com/{fb_id}/picture?width=200&height=200&redirect=false
When I access from browser, it return something like this
So I am trying to retrieve that data as json and then serialize them back. So I builds two classes like below to bind that data.
public class FacebookAvatarResponse
{
[JsonProperty("data")]
public FacebookAvatarData Data { get; set; }
}
public class FacebookAvatarData
{
[JsonProperty("height")]
public int Height { get; set; }
[JsonProperty("width")]
public int Width { get; set; }
[JsonProperty("is_silhouette")]
public bool IsSilhouette { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
}
In controll, I built an action method
[AllowAnonymous]
public JsonResult Test(string avatarDataUrl)
{
using (WebClient webClient = new WebClient())
{
string data = webClient.DownloadString(avatarDataUrl);
return Json(JsonConvert.DeserializeObject<FacebookAvatarResponse>(data),JsonRequestBehavior.AllowGet);
}
}
As you can see I am getting that data as json and then return as action result. But when I request that action method passing correct url as parameter, it is giving me this error.
How can I retrieve JSON data from remote server binding to the specific classes?
Possibly your are not passing JSON to DeserializeObject.
JsonConvert.DeserializeObject takes JSON value.
Check your data should be in json format to deserialize.
Json(JsonConvert.DeserializeObject<FacebookAvatarResponse>(data),
JsonRequestBehavior.AllowGet);

Fiddler post request to .net mvc controller returns 404

I have controller which is
[HttpGet]
public IHttpActionResult GetUserRights(int id)
{
var rights = _rightsService.GetUserRights(id);
if (rights == null)
{
return new HttpActionResult(HttpStatusCode.BadRequest, "User not found");
}
return Ok(rights);
}
[HttpPost]
public IHttpActionResult SetUserRights(int id, IEnumerable<EditRightViewModel> rights)
{
Result result = _rightsService.SetUserRights(id, rights);
if (!result.IsSuccess)
{
return new HttpActionResult(HttpStatusCode.InternalServerError, result.Message);
}
return Ok(result.Data);
}
[HttpPost]
public IHttpActionResult SetUserRights(int id, int RightId, bool Enable)
{
Result result = _rightsService.SetUserRights(id, new List<EditRightViewModel>
{
new EditRightViewModel
{
RightId = RightId,
Enable = Enable
}
});
if (!result.IsSuccess)
{
return new HttpActionResult(HttpStatusCode.InternalServerError, result.Message);
}
return Ok(result.Data);
}
The get request works fine but the post returns 404.
The request is
User-Agent: Fiddler
Host: localhost:577
Content-Length: 44
Content-Type: application/json; charset=utf-8
{
"id":1,
"RightId":1,
"Enable":"true"
}
Originally I want to send data to the post action that has a list as parameter. I thought that reason why it returns 404 is that json doesn't fits the function's arguments. So I simplified json and action parameters but it still won't work. Maybe someone can tell what's the reason of the problem and how to write a correct json to send list as a parameter?
404 Errors mostly occur when you Method signature does not match your POST data or when your Routing is not configured correctly.
Have a look at my answer here - Webservice return 404
I would change the Method signature to accept a class instead.
public class UserRights
{
public int id {get;set;}
public int RightId {get;set;}
public bool Enable {get;set;}
}
Post Actions can not have most one argument in body.
Create a class with the parameters you need. ASP NET will do the binding.
public IHttpActionResult SetUserRights(Right right){ /* ... */ }
public class Right {
public int id { get; set; }
public int RightId { get; set; }
public bool Enable { get; set; }
}
Try this.

Form-Data array not being deserialized to request dto

I'm trying to do filtering function for KendoUI Grid.
Kendo sends data as form-data:
take:20
skip:0
page:1
pageSize:20
filter[filters][0][operator]:eq
filter[filters][0][value]:abc
filter[filters][0][field]:No
filter[logic]:and
I tried to deserialize it using dto:
public class FilteringRule
{
public string Field { get; set; }
public string Operator { get; set; }
public string Value { get; set; }
}
public class FilteringInfo
{
public string Logic { get; set; }
public FilteringRule[] Filters { get; set; }
}
public class FilteredQuery
{
FilteringInfo Filter { get; set; }
//...
}
but deserialization fails:
'filter[filters][0][operator]' does not exist on type 'FilteredQuery'
'filter[filters][0][value]' does not exist on type 'FilteredQuery'
'filter[filters][0][field]' does not exist on type 'FilteredQuery'
'filter[logic]' does not exist on type 'FilteredQuery'
How to make this work? When I manually send json instead of form-data it works.
Can kendo send json? Setting contentType: "application/json" in datasource doesn't help. Kendo still sends data as form-data, servicestack throws error: "unable to bind request".
ServiceStack allows sending complex objects via QueryStrings using the lightweight JSV Syntax which from your example would look something like:
?filter={filters:[{operator:eq,value:abc,field:no}],{logic:and}}
But since Kendo is unlikely to support this syntax, you would be better off sending JSON if it supports it which would naturally map to your DTOs.