Json object in post not recognized as object in web api - c#

I have an angular client and want to execute a get request to my web api backend to get a list of items from the underlying Dapper Db Wrapper. Dapper allows me to pass in parameters as an anonymous object which would in csharp look like this:
connection.GetList<T>(new {myParam1:"a", myParam2: true});
What I want to achieve is, to create this parameter object in my angular frontend and pass it in a post request to the server which would then pass it on to the GetList function. The problem here is that the web api does not deserialize it as an (anonymous) object, but rather and IEnumerable of JTokens?
My web api signature is this:
public async Task<IHttpActionResult> MyFunction([FromBody]dynamic whereCond)
I have also tried to pass the object as string wrapped in an outer object like so (angular client):
this.migController.MigrationGetMigrationReports({whereCond: JSON.stringify({NotMigrated: true, MissingTargetFiles: 0})})
and then on the server I manually deserialize it as JObject:
string obj = whereCond.whereCond;
dynamic pObj = JObject.Parse(obj);
But this results in the exact same result: pObj is an IEnumerable and therefore I get an error message from the GetList call:
An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context
can anybody help?

The answer to my question turned out rather simple:
dynamic pObj = JObject.Parse(obj).ToObject<ExpandoObject>();
I had to cast it as ExpandoObject not just dynamic.
#Tsahi: this is not a design problem. My intention was to provide the server with parameters (filter) which is a quite common task for a client to reduce the dataset to be transferred. We could debate a standard way how to provide these parameters, however. In my special case the most practical way is the anonymous object.

Related

Working with dynamic data with Azure DocumentDB and MVC5

I am working with Azure DocumentDB using dynamic data types, i.e., I do not predefine any classes for the data I'm working with. I'm querying my DocumentDb database/collection using calls of the form:
client.CreateDocumentQuery<dynamic>(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), query).ToArray();
The objects that get returned seem to be of type Micrsoft.Azure.Documents.QueryResult.
When the query is included as part of an MVC action, when the results are passed back to the client they become empty objects.
I was expecting to get 'dynamic' data back which would serialize just fine as part of the JsonResponse.
What do I need to do to convert each Micrsoft.Azure.Documents.QueryResult to dynamic?
According to your description, I tried to build my MVC Web Application and I could encounter the same issue as you mentioned.
I was expecting to get 'dynamic' data back which would serialize just fine as part of the JsonResponse.
You could leverage the following code:
var results=client.CreateDocumentQuery<dynamic>(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), query).ToArray();
return Content(JsonConvert.SerializeObject(results), "application/json");
Result

What is the best way to serialize, return and consume complex C# object from an MVC3 app?

Here's my situation: I have an MVC3 app that has some very complex C# objects, and those get rendered to a views in this application. However, I have a new requirement: a console application (that I am also writing) will run under a scheduler, and it needs to pull these objects from this MVC3 app, and then do something else with these complex objects.
Since I have control over both apps, I can share a library of the complex objects between them. All of these objects are marked [Serializable]. However, I cannot figure out an easy way to serialize these objects and send them from the MVC3 app to the Console app.
I tried simple JavaScriptSerializer and using the HttpClient to read the string, then deserialize it on the console-app end of things, but unfortunately it doesn't deserialize the data correctly. Everything is null. I can inspect the string on a breakpoint when it arrives at the console app, and all the data is there, in the string, but it just doesn't get de-serialized correctly.
Is there an easier way to do this? I don't care what the serialization method is. The data doesn't have to be passed as JSON and no other application but mine is going to consume these objects. But so far I can't figure out the easiest way to produce/consume these objects.
I know I can go down the whole "create a web service contract" and use data annotations route, but I was hoping there was an easier, less time-consuming way of doing it.
Using Json.NET:
Server-Side
string serializedObject = JsonConvert.SerializeObject(yourComplexObject);
// Send the string to the client...
Client-Side
In the client, you don't even have to know the deserialized object's type, you can take advantage of anonymous objects and dynamic:
string serializedObject = // ... Fetch from server
dynamic complexObject = JsonConvert.DeserializeObject(serializedObject);
// ...
string id = complexObject.UserId;
P.S.: Please note that the object's methods or state is not going to get serialized, only the public properties are.
Can your action just return your object? If so, your client code would look something like (using HttpClient)
var result = client.GetAsync(url).Result;
var myObj = await result.Content.ReadAsAsync<T>();

Create a manual property binder in c#

I have a task I am trying to complete, and trying to do it the best way possible.
Let say I have a jObject
var jobj = {val1: 1, val2: "s"} // on server
and I need to user the properties in that object as the params for a Method.Invoke call.
someMethod.Invoke(class, params);
I need some way to take the properties from the JObject and convert them into an array of objects to pass to the invoke method.
I can easily get the param details
var param = Method.GetParameter("ParameterName");
this will give me the value, type be it a string or a complex object.
While a believe I could write the code to do this I think it would be better to use built in .Net functionality if it exists.
.Net does very similar conversions for all WEB_API and MVC Controller calls, and I would like to tap into those existing functions to do the work as they are probably very well vetted, but I am having trouble finding out how it is done.
I have found the IActionValueBinder and the DefaultModelBinder but I cannot figure out how to use these outside the context of a standard controller.

Pass DTO for GET Request in REST

I have a REST method for search users. Right now I am having following signature for the REST method:
MyResponse GetUsers(UserSearchDTO search, int pageno, int totalrecords);
i.e it is accepting one object of UserSearchDTO, pageno and totalrecords param. The URL will look like
myapp/users?pageno={pageno}&totalrecords={totalrecords}
The end client will send "PUT" request for this service like:
myapp/users?pageno=1&totalrecords=10 and along with it it will pass xml data posted of UserSearchDTO like
<UserSearchDTO><Department>d</Department><Name>abc</Name></UserSearchDTO>
Is this a good architecture i.e in order to get users I am using "PUT" request type. The reason for doing this is because end client has to pass UserSearchDTO in xml form?
The other approach which I'm thinking is pure "GET" i.e instead of using UserSearchDTO I should have the following signature:
MyResponse GetUsers(string department,string name,...., int pageno, int totalrecords);
and the end client will call it like:
myapp/users?department=d&name=abc&......&pageno=1&totalrecords=10
I am in the process of writing my first REST service, so I am no expert, but in my opinion, I think it would be best to use a GET request, since that is exactly what you are doing -- getting data from the server. This will make it easier for other developers to support the app, instead of trying to figure out why you used PUT for a basic data retrieval.
If possible, I suggest that you try casting the UserSearchDTO XML as a string on the client and passing it to the GetUsers method as a string, then load the string into an XmlDocument() on the server and parse it into the DTO. Then your method signature would look like:
MyResponse GetUsers(string userSearchXmlString, int pageno, int totalrecords);
It looks like you're using WCF REST. With WCF REST, you have to implement the query mechanisms yourself as you are attempting to do. Have you considered using ASP.NET Web API? In Web API, your GetUsers() method simply needs to return an IQueryable<User> and Web API wraps that with OData querying capability which handles projection, filtering, sorting, aggregating and paging for you.

Can I pass a linked list from a C# Web Service to a JavaScript function?

I've created a linked list class in my JavaScript code and then translated that code into C#.
Right now I have a JavaScript function that calls a Web Service in order to get an array of names, the JavaScript onComplete function then takes that array and makes it into a linked list.
Is there any way I can create the linked list in the Web Service and pass it back to be used by the JavaScript code or can linked lists not transfer properly?
Edit: Let me rephrase my question to something that makes a little more sense. If you have a custom made object created by a class say.... class User, and that class has a variable called user name. If you pass a User object: objUser, back from C# to JavaScript, how does the JavaScript know it can access objUser.userName? What about possible methods it can invoke on this user object?
I had a similar question when I was creating my ASP.NET MVC application. Basically the answer is that JavaScript does not have the same concept of Types as in C#.
Let's say that you've decided to use JSON to pass data between your client and server in your application. The choice of JSON, XML, YAML or other format is not important.
Server Side
On your server side, in your C# code, you can do something like this (assuming you are using a JSON library of some sort):
var myLinkedList = JsonConvert.DeserializeObject<LinkedList>(json);
Now you've got a myLinkedList variable of Type LinkedList. myLinkedList now behaves like all LinkedList instances.
Client Side
However on the client site, in your JavaScript code, you probably do something like this:
function LinkedList(){
//Constructor for your LinkedList
};
LinkedList.prototype = {
//Various functions to operate on your linked list
};
You need to write something like this to deserialize the data that returns from the server:
var linkedList = JSON.parse(jsonString);
Note that there is NO WAY to indicate that you want this deserialized data to go into the LinkedList "class" that you've defined earlier. JavaScript does not understand that LinkedList is a "class" that you've added functionality to using prototype.
What you get back is a JavaScript object.
One way to get around this is to do something like this:
var linkedList = new LinkedList();
var deserializedObject = JSON.parse(jsonString);
linkedList.Items = deserializedObject.Items;
Basically, you'd have to copy over all the state from your deserialized object into your linkedList variable.

Categories

Resources