How to see HttpResponseMessage client side? - c#

I am an experienced programmer but new to WebApi (We're using MS asp.net mvc framework).
A customer requested that all return values be wrapped in an object of this sort:
{
success: [boolean],
errorLog: [error message, if failed],
referer: [api call details],
payload: {
// results, if success
}
I saw that the standard already called for returning an HttpResponseMessage object, which has this information. So, rather than duplicating, I just return an object of this type (either directly, or via an IHttpActionResult, e.g.
return Ok(object);
However, I cannot see how to use this object from the client side. When I make an api call from the browser, all I see is the content (even using the debugger). When I return an error, I see:
<Error>
<Message>foo bar</Message>
</Error>
but no sign of the other info (StatusCode, ReasonPhrase, etc.). The same applies if I return Json format.
Is this object 'stripped' somewhere along the line, and if so by who? How can I allow this object to arrive to the api caller so s/he can use all the associated fields?
Thanks
Edit: As requested by comment, I'm posting my server-side code, though there isn't much to it. My attempt at seeing the HttpResponseMessage object was to create this controller:
public HttpResponseMessage Get() {
HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.NotAcceptable, "foo bar");
response.ReasonPhrase = "There is no reason.";
return response;
}
This is the code which results in the xml posted above.

Is this object 'stripped' somewhere along the line, and if so by who?
The object will be stripped by HttpResponseMessage under the hood when you return IHttpActionResult a call to ExecuteAync to create an HttpResponseMessage.
So in order to see all fields you should use a tools like fiddler in raw mode or extension like HttpHeader for chrome.
How can I allow this object to arrive to the api caller so s/he can use all the associated fields
One way to send the expected answer is to create a POCO like this
public class Payload
{
}
public class CustomResponse
{
public IList<bool> Success { get; set; }
public IList<string> ErrorLog { get; set; }
public IList<string> Referer { get; set; }
public Payload Payload { get; set; }
}
and send the answer like this
return OK(new CustomObject(){Payload=yourObject});

Related

How to handle a Json Post with different structure from what was expected in a API

I am developing a API using OWINHost and in my controller i've got an post method that is expecting a Json. If the Json is structured properly, everything is working just fine, but i am not being able to throw an error if the structure is different.
I thougth about instead of receive a type "SMS" as an parameter, receives a string then use Newtonsoft.Json to parse that string, if it parses incorrectly throw the error, but i am not sure if this is good pracctice.
[HttpPost]
public HttpResponseMessage NewMessage(HttpRequestMessage request, [FromBody] SMS sms)
{
// some code
//return Ok if everything runs smoothly
return request.CreateResponse(HttpStatusCode.OK);
}
I need to know when the structure of the json is incorrect so i can throw an error status.
{
"Number": "12345",
"Content": "Test"
}
This is the json structure, and this is my SMS class
public class SMS
{
public string Number{ get; set; }
public string Content{ get; set; }
}

complex object is empty when use in Web API input

I have a method in Web API that I used the object as input, but when I try to run the API using URI the fields inside the object are Null.
this is my method:
[HttpGet]
[Route("AddUser/{user}")]
public async Task<string> CreateUser([FromUri]AddUser user)
{
//LoansApiTrace.Trace.Verbose(EventId.Start, () => string.Format("{0}: {1}", "AddUser", user.));
string Exception = await Repository.AddUserAsync(user);
return Exception;
}
This is AddUser object:
public class AddUser
{
public string UserEmailAddress { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
public string RemoteRefNumber { get; set; }
}
and this is the URI:
http://localhost:59509/Adduser/user=test#yahoo.com,pass,salt,remref/
it goes to the method but UserEmailAddress , PasswordHash ,..all 4 are empty.
This is a really a bad practice to pass secret data through URI like you're doing. Then I will not attempt to give a solution for that to work.
The best practice is to pass that kind of data through your request body and use Http POST method :
[HttpPost]
[Route("AddUser/{userId}")]
public async Task<string> CreateUser(string userId, [FromBody]AddUser user)
{
// Find a user by userId
// Then update the user data.
}
you use an URI like this => http://localhost:59509/Adduser/12345 where 12345 is the user id.
you need to make sure that the selected HTTP method is POST
you need to write the data of AddUser into the request body
It also recommanded to use HTTPS when user need to send that type of data.
Consider Using POST If Applicable
While it may not be do-able, you may want to consider adding these fields within a <form> and simply posting them to the server in the body as opposed to using the actual URL itself. Passwords, salts and hashes generally aren't something that you want to get passed around like that.
If You Must Use A GET
Have you tried passing the values in as proper query-string parameters instead?
http://localhost:59509/Adduser/user?UserEmailAddress=test#yahoo.com&PasswordHash=abc&Salt=123&RemoteRefNumber=foo
This should set the following properties based on your current routes:
user = "user"
UserEmailAddress = "test#yahoo.com"
PasswordHash = "abc"
Salt = "123"
RemoteRefNumber = "foo"
MVC has to have some idea of how to bind these properties to those on your class, so unless the names match as expected, it will not know how to map something like "user" to "UserEmailAddress". As mentioned earlier, this isn't ideal and can present all sorts of security issues (so only use something like this on prototype / non-production environments).

Can I manually hard code a JSON object to be returned by ASP.NET web API?

I'm used to doing this in Django (similar to Ruby on Rails) where in some cases I need to hard code a JSON response object for the client to be able to interpret, but I've been searching everywhere online on figuring out how to do this with ASP.NET web API and I can't find anything on this, ASP.NET web API seems to be forcing me to create a class to represent a JSON response for every URI controller.
For example, here's the only way I know for manually creating a JSON response:
1.) I first need to create the class to represent the response object
public class XYZ_JSON
{
public string PropertyName { get; set; }
public string PropertyValue { get; set; }
}
2.) Then I need to properly write up the URI controller that'll return an "XYZ_JSON" that I've just defined above:
// GET: api/ReturnJSON
public XYZ_JSON Get()
{
XYZ_JSON test = new XYZ_JSON { PropertyName = "Romulus", PropertyValue = "123123" };
return test;
}
Will result with an http response of something like:
200 OK
{"PropertyName":"Romulus", "PropertyValue":"123123"}
This whole class to JSON design pattern is cool and all, but it's not helpful and actually makes things much worse when trying to return a class as a JSON object with many classes within it such as:
public class XYZ_JSON
{
public string PropertyName { get; set; }
public string PropertyValue { get; set; }
public List<ComplexObject> objects { get; set; } // <- do not want
}
The JSON response object above isn't that complex, but for what I'm trying to accomplish I'll have to put a list of classes within a list of classes within a list of classes, and I can't develop it in this awkward way unless I spend a week on it which is just ridiculous.
I need to be able to return a JSON response in this kind of fashion:
// GET: api/ReturnJSON
public JSON_Response Get(string id)
{
// do some SQL querying here to grab the model or what have you.
if (somethingGoesWrong = true)
return {"result":"fail"}
else
return {"result":"success","value":"some value goes here"}
}
The design pattern above is what I'm trying to accomplish with ASP.NET web API, a very simply way to return a semi-hard coded JSON response object which would allow me to return very unique and dynamic responses from a single URI. There's going to be many use cases where a list of up to 8 completely unique Class objects will be returned.
Also, If what I'm trying to accomplish is the backwards way of doing things than that's fine. I've released a very successful and stable iOS application with a flawless Django backend server handling things this way perfectly without any issues.
Can someone explain to me how I can return a simple hard coded JSON response using the ASP.NET web API?
Thanks!
You can create anonymous types in C#, so you can use one of these to produce your hard-coded result. For example:
return new JsonResult
{
Data = new
{
result = "success",
value = "some value"
}
};
To clarify, the above code is for ASP.NET MVC. If you're using Web API, then you can just return the data object, or use an IHttpActionResult. The anonymous type part (the new {}) stays the same.
Use an anonymous object.
public object Get(string id)
{
// do some SQL querying here to grab the model or what have you.
if (somethingGoesWrong = true)
return new {result = "fail"}
else
return new {result = "success", value= "some value goes here"}
}
You can use a generic JObject to return your values without constructing a complete class structure as shown below
public JObject Get(int id)
{
return JsonConvert.DeserializeObject<JObject>(#"{""result"":""success"",""value"":""some value goes here""}");
}
For hard coded response, why not just do something like below. The JSON content will be returned without being surrounded by quotation marks.
public HttpResponseMessage Get()
{
string content = "Your JSON content";
return BuildResponseWithoutQuotationMarks(content);
}
private HttpResponseMessage BuildResponseWithoutQuotationMarks(string content)
{
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(content);
return response;
}
private HttpResponseMessage BuildResponseWithQuotationMarks(string content)
{
var response = Request.CreateResponse(HttpStatusCode.OK, content);
return response;
}
// GET: api/ReturnJSON
public JsonResult Get()
{
return Json(new { Property1 = "Value1", Property2 = "Value2" });
}
You can return json using JsonResult class. and the Json() method takes anonymous object so you don't need to create a class.

Exception when returning list of objects with servicestack

I am attempting to get ServiceStack to return a list of objects to a C# client, but I keep getting this exception:
"... System.Runtime.Serialization.SerializationException: Type definitions should start with a '{' ...."
The model I am trying to return:
public class ServiceCallModel
{
public ServiceCallModel()
{
call_uid = 0;
}
public ServiceCallModel(int callUid)
{
this.call_uid = callUid;
}
public int call_uid { get; set; }
public int store_uid { get; set; }
...... <many more properties> ......
public bool cap_expense { get; set; }
public bool is_new { get; set; }
// An array of properties to exclude from property building
public string[] excludedProperties = { "" };
}
The response:
public class ServiceCallResponse
{
public List<ServiceCallModel> Result { get; set; }
public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized
}
And the service:
public class ServiceCallsService : Service
{
// An instance of model factory
ModelFactory MyModelFactory = new ModelFactory();
public object Any(ServiceCallModel request)
{
if (request.call_uid != 0)
{
return MyModelFactory.GetServiceCalls(request.call_uid);
} else {
return MyModelFactory.GetServiceCalls() ;
}
}
}
The client accesses the service with:
JsonServiceClient client = new ServiceStack.ServiceClient.Web.JsonServiceClient("http://172.16.0.15/");
client.SetCredentials("user", "1234");
client.AlwaysSendBasicAuthHeader = true;
ServiceCallResponse response = client.Get<ServiceCallResponse>("/sc");
The "model factory" class is a DB access class which returns a list. Everything seems to work just fine when I access the service through a web browser. The JSON returned from the service starts:
"[{"call_uid":70...."
And ends with:
"....false,"is_new":true}]"
My question is, what here might be causing serialization/deserialization to fail?
Solution
Thanks to the answer from mythz, I was able to figure out what I was doing wrong. My misunderstanding was in exactly how many DTO types there are and exactly what they do. In my mind I had them sort of merged together in some incorrect way. So now as I understand it:
Object to return (In my case, called "ServiceCallModel": The actual class you wish the client to have once ServiceStack has done its job. In my case, a ServiceCallModel is a key class in my program which many other classes consume and create.
Request DTO: This is what the client sends to the server and contains anything related to making a request. Variables, etc.
Response DTO: The response that the server sends back to the requesting client. This contains a single data object (ServiceCallModel), or in my case... a list of ServiceCallModel.
Further, exactly as Mythz said, I now understand the reason for adding "IReturn" to the request DTO is so the client will know precisely what the server will send back to it. In my case I am using the list of ServiceCallModel as the data source for a ListView in Android. So its nice to be able to tell a ListViewAdapter that "response.Result" is in fact already a useful list.
Thanks Mythz for your help.
This error:
Type definitions should start with a '{'
Happens when the shape of the JSON doesn't match what it's expecting, which for this example:
ServiceCallResponse response = client.Get<ServiceCallResponse>("/sc");
The client is expecting the Service to return a ServiceCallResponse, but it's not clear from the info provided that this is happening - though the error is suggesting it's not.
Add Type Safety
Although it doesn't change the behavior, if you specify types in your services you can assert that it returns the expected type, e.g Change object to ServiceCallResponse, e.g:
public ServiceCallResponse Any(ServiceCallModel request)
{
...
}
To save clients guessing what a service returns, you can just specify it on the Request DTO with:
public class ServiceCallModel : IReturn<ServiceCallResponse>
{
...
}
This lets your clients have a more succinct and typed API, e.g:
ServiceCallResponse response = client.Get(new ServiceCallModel());
instead of:
ServiceCallResponse response = client.Get<ServiceCallResponse>("/sc");
See the New API and C# Clients docs for more info.

.NET MVC API - dots (period) in get request

I'm trying to setup Facebook Notification API.
I have an APi Controller with RealtimeUpdate() - Get, will be used just for verification of endpoint.
As is written in Fb Docs:
Firstly, Facebook servers will make a single HTTP GET to your callback
URL when you try to add or modify a subscription. A query string will
be appended to your callback URL with the following parameters:
hub.mode - The string "subscribe" is passed in this parameter
hub.challenge - A random string
hub.verify_token - The verify_token value you specified when you created the subscription
From here I have a problem - I have no idea how to handle this dots in query params names. I google a lot, and did not find the solution.
Can somebody please say to me how to get data from this hub.* values?
Thank you!
Update your method signature using the FromUri attributes, like this:
public string Get(
[FromUri(Name="hub.mode")]string mode,
[FromUri(Name="hub.challenge")]string challenge,
[FromUri(Name="hub.verify_token")]string verifyToken
)
{
/* method body */
}
The parameters will be bound from the query string using the specified names.
Slightly different form Steve's answer.
In case you need to have a normal controller instead of an Api one (if you are inheriting from Controller rather tha ApiController), the follow worked for me:
namespace Name
{
public class Hub
{
public string Mode { get; set; }
public string Challenge { get; set; }
// ReSharper disable once InconsistentNaming
public string Verify_Token { get; set; }
}
public class FacebookWebHooksController : Controller
{
[System.Web.Http.HttpGet, ActionName("Callback")]
[AllowAnonymous]
public ContentResult CallbackGet(Hub hub)
{
if (hub.Mode == "subscribe" && hub.Verify_Token == "YOUR_TOKEN")
return Content(hub.Challenge, "text/plain", Encoding.UTF8);
return Content(string.Empty, "text/plain", Encoding.UTF8);
}
}
[HttpPost]
[AllowAnonymous]
public ActionResult Callback()
{
Request.InputStream.Seek(0, SeekOrigin.Begin);
var jsonData = new StreamReader(Request.InputStream).ReadToEnd();
}
}
The Model Binder has some illegal characters, of which I believe '.' is a special character, used primarily to bind complex objects. When all else fails, you can look at Request.QueryString and Request.Form directly, just like in ASP.NET WebForms.
You can also try using a complex object that has a Property named hub with subproperties mode, challenge, and verify_token. This might just do the trick.

Categories