I was looking at https://stackoverflow.com/a/15873977 but it didn't work for me.
If my Post method has a parameter named Message (an object of my own class), and I do not apply the [FromBody] attribute to it, is it possible to pass the parameter Message, json serialized and urlEncoded, on the query string instead of in the Post body?
I tried passing ?Message=%7B+%22Sender%22%3A...+%7D (which if decoded would be Message={ "Sender":... }) but the Message parameter is still received as null in the method.
Should the query string key be Message, the name of the parameter, or the class name of the parameter or something else?
If you have a model Foo:
public class Foo
{
public string Bar { get; set; }
public int Baz { get; set; }
}
And you want to bind this from the query string, then you must address the individual properties:
?Bar=qux&Baz=42
And annotate that the model must be bound from the query string:
public void Bar([FromUri]Foo foo)
{
}
If you really want to send JSON into your action method and not a model, simply bind to a string instead of a model. You can then do whatever you want with the JSON string inside your action method.
Related
I have an action method already written in my web api 2.0 project. I would like to add a new parameter without disturbing the existing contract. What is the best way to do that? Appreciate any best practice hints on this :)
Here's the code sample of what I intend to do:
Existing code:
[Route("{myId}",Name="MyId")]
Public IHttpActionResult Get(String myId)
{
//Some more code here
}
Url: http://localhost:8888/webapi/1111
Expecting to do something like the below:
//I want to keep the route name same for backwards compatibility.
[Route("{myId}/{myName}",Name="MyId")]
Public IHttpActionResult Get(String myId,string? myName)
{
//Some more code here
}
Url: http://localhost:8888/webapi/1111/John
The Url mentioned above hits the method rightly, but I never get the second parameter (myName) populated with John.
Thanks everyone for any help towards this.
Sree.
In your example you have myName as string? which is not allowed as:
The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable'
A test controller was created to implement you action
[RoutePrefix("webapi")]
public class TestsController : ApiController {
[HttpGet]
[Route("{myId}/{myName}", Name = "MyId")]
public IHttpActionResult Get(string myId, string myName) {
//Some code to show the values of the parameters
return Ok(new { myId = myId, myName = myName });
}
}
When tested with webapi/1111/John the following response is returned
{"myId":"1111","myName":"John"}
which does include the value for MyName as John
If backwards uri webapi/1111 is tried, a NotFound response is returned as the template does not match the new action.
To fix this you need to make the myName parameter optional. To learn more about that check
Optional URI Parameters and Default Values
The new route will look like
//NOTICE THE `?` ON THE {myName} TEMPLATE
[Route("{myId}/{myName?}", Name = "MyId")]
public IHttpActionResult Get(string myId, string myName = null) {...}
You will notice that myName was made optional in the route {myId}/{myName?} and in the action parameter (string myId, string myName = null)
Now when tested with webapi/1111 the following response is returned
{"myId":"1111","myName":null}
Which would match your expected result for backwards compatibility.
String is a reference type so you don't need to make it nullable, it already is. Remove the '?' and remove the Name from the attribute. What happens then?
i have a index.jsp home page which has following checkboxlist to select the favorite fruit:
friuts that i like : <s:checkboxlist name="myFruits" list="{'apple','mango','orange'}"/>
in the actionssupport file, i have used the 'myFruits' String type. :
public class Action1 extends ActionSupport
{
String myFruits;
public String getMyFruits() {
return myFruits;
}
public void setMyFruits(String myFruits) {
this.myFruits = myFruits;
}
public String execute()
{
return "success";
}
}
And the results.jsp which reads the selected values :
my favorite fruit is:<br>
<s:property value="myFruits"/>
the output comes up correctly.
my favorite fruit is:
apple, mango
But i am not able to understand how the multiple values selected for example apple and mango are getting stored in valuestack with String myFruit type. Shouldn't this be a List or an array?
Why the above code works fine with just a String type to hold multiple String names?
But I am not able to understand how the multiple values selected for example apple and mango are getting stored in valuestack with String myFruit type. Shouldn't this be a List or an array?
You have a string property with the name myFruits and parameters with the same name. Struts is doing the best to populate that property, and if the parameter has multiple values but a property is a single string type, they could be converted as string with values separated by comma.
On the other hand if you have an array or list property type, the values will be set as array or list.
I've got one method, which take a model [AccountLinkRequest] as a parameter with url-encoded data. It's uses Json.NET by default, and also, I can't use the setting UseDataContractJsonSerializer = true cause I have generic output response model (in other methods)
[HttpPost]
public SomeResponse Link(AccountLinkRequest request)
{
if (request.CustomerId == null)
throw new Exception("Deserialization error here, pls help!");
// other actions
}
Here is my model class:
[DataContract]
[JsonObject]
public class AlertAccountLinkRequest
{
[DataMember(Name = "id")]
public string id { get; set; }
[DataMember(Name = "customer_id")]
[JsonProperty("customer_id")]
public string CustomerId { get; set; }
}
The problem: request.CustomerId is allways null. The request is pretty simple:
web_service_URL/link?customer_id=customer_id&id=id (url-encoded)
if I use Customer_Id instead of CustomerId, everything will be fine, but I'm on a jedy-way. Thank you!
There is not a simple answer how to achieve that. For more details please read this:
How to bind to custom objects in action signatures in MVC/WebAPI
Summary:
Manually call the parse function inside of your Action
Use a TypeConverter to make the complex type be simple
Use a custom model binder
So, if you for instance create your 'SmartBinder' which is able to consume some attributes, you can get what you want. Out fo the box there is no functionality for that, just the naming conventions...
I'm trying to pass a null value in a JSON object let's say: { 'property': null } to a controller action in ASP.Net MVC but in the action method I see the property gets a zero value instead of null.
What can I do about this?
just dont send that property or delete that in the client-side : delete x.yourProperty
for example if you have some .net mvc controller with a nullable property like this:
public JsonResult SomeAction(decimal? yourProperty){ //your code goes here }
if in the client-side you call some ajax request with yourProperty: null the model binder will set it to 0, like as int or string that will be set to EmptyString
so if you want to send it as null you just avoid sending it, or if it's a property that you have set before all you need is to just delete that property: delete x.yourProperty
The property on your model should be a nullable decimal if you want this to work:
public decimal? MyProperty { get; set; }
I am using Reflection provider for my WCF Data Service and my Data Context object has two key members, say EmpId and DeptId.
If I specify [DataServiceKey("EmpId", "DeptId")], the service doesn't work. When I try to access the collection with the URL http://localhost:55389/DataService.svc/EmployeeData, I get the following error:
The XML page cannot be displayed
Cannot view XML input using XSL style
sheet. Please correct the error and
then click the Refresh button, or try
again later. The following tags were
not closed: feed. Error processing
resource
'http://localhost:55389/DataService.svc/EmployeeData'.
With single member in the DataServiceKey, it works fine. I tried with Custom Data Provider and I could achieve this functionality. But if I can do it with the Reflection provider, that would be great.
I don't think the problem is the multiple keys. To confirm please use for example Fiddler or something similar to grab the whole response from the server and share the error in it (as I'm sure there will be one in there).
Guessing from the description I think the problem is that one of your key property values is null. That is not supported and would cause so called in-stream error which would leave the response XML incomplete (which seems to be your case).
OData can handle multiple keys but all keys must have a valid value. Review this for OData's rule. If you want to retrieve an entry with EmpId=1 and DeptId=someString, you should reconstruct your URI into something like:
http://localhost:55389/DataService.svc/EmployeeData(EmpId=1,DeptId='someString')
Be careful in OData queries because they are case sensitive.
That is weird, I just tried this:
public class Context
{
public IQueryable<Person> People {
get {
return (new List<Person> {
new Person { EmpId = 1, DeptId = 2, Name = "Dude" }
}).AsQueryable();
}
}
}
[DataServiceKey("EmpId", "DeptId")]
public class Person
{
public int EmpId { get; set; }
public int DeptId { get; set; }
public string Name { get; set; }
}
public class WcfDataService1 : DataService<Context>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion =
DataServiceProtocolVersion.V2;
}
}
And it works just fine, do you notice any major differences?
-Alex