I have an MVC WebApi app. I'm trying to do something basic - pass a string via JSON in the body. My client submits a small number of key/value parameters, and when the MVC router gets them, it begins to interpret the content of the strings.
An example JSON body is
{ "myKey":"red,yellow,brown,orange","foo":"bar" }
My MVC controller method is
public Dictionary<string, string> PostMyAction([FromBody] str1, [FromBody] str2) { }
I would expect str1 == "red,yellow,brown,orange" but instead I get "Can't bind multiple parameters ('str1') to the request's content."
Why is it parsing the first string as a list of parameters?
Shouldn't your Controller method be an ActionResult?
You do can receive more than one parameter on your actions, but for a clear code, I recomend use one ViewModel that contains properties that will represent your View, and Binded on submit.
Related
Usually I send my post request with a custom parameter and a custom return and object using
HttpClientExtension.PostAsJsonAsync<T>
This allows my to call a post method with a custom object.
Now, I want to be able to send my custom object as a parameter and return value to a GET Method.
Lets say my method signature is
[HttpGet]
public MyMethodResponse MyMethod(MyMethodRequest request)
How can I send a request when I have an instance of MyMethodRequest ?
Thanks.
You need to encode MyMethodRequest onto the query string. You can either encode it as separate query string parameters or as a single one. You have handle the encoding yourself on the client side, remembering to URI-encode the parameters. Decoding is done using a custom ModelBinder or TypeConverter respectively. This article shows examples of binding a complex object on the query string.
I have the following controller to take four parameter and one to get an array of string.
public Response Get(string a, double b, double c, string[] d)
{
do something
}
As u see the fourth(d) parameter is an array of strings. The first 3 parameter get the value but d shows null.
I am using fiddler to debug with following url
04/api/Controller?a=Hello&b=-37.8031231&c=144.9836514&d=Italian&d=bars
What m i doing wrong? is it the url?
Without seeing your View, I can abstract that you named 2 inputs as name='d' without indexing
example:
You can create an array by naming your id inputs with array indexes.
#using (Html.BeginForm())
{
<input type="text" name="d[1]">
<input type="text" name="d[2]">
}
If you index your inputs, the framework will use them as a List
Note:
you bring up URL. You cannot pass an array or any complex object without a Post.
You can post array data from fiddler, the URL you have provided is correct. But make sure you have the correct content type in request header.
you don't have to create view to test your controller action method.
Client request
Server respone
P.S. Above provided is for controller action method, I have noticed you are using api controller after posting the answer. I will edit the answer once done for api controller.
The Above works for APIController as well, If you are posting from fiddler
I have these two methods in the same Controller, the first passing two parameters to the second.
When debugging, the list (model.RequestedProducts) passed is correct (not empty) but on the second method, only idOR is read correctly, List<OCS> RequestedProducts is empty.
[HttpPost]
public ActionResult Index(int idOR, ViewModel model, string add, string remove, string send)
{
//...
return RedirectToAction("Done",
new { idOR = idOR,
RequestedProducts = model.RequestedProducts});
}
public ActionResult Done(int IdOR, List<OCS> RequestedProducts)
{ ...
What am I missing?
Is there maybe a better way to do it? (other than Redirect to Action)
Thank you
When you use RedirectToAction you are returning a message to the client to request a new URL probably something like /controller/action/id. You Routes will define how the URL is formed. I am guessing you have the default route defined and in your case MVC has no way of knowing how to deserialise your RequestedProducts type into a URL and then bind it back into a List type.
Instead you could use the TempData object to pass data between to Action requests.
The TempData property value is stored in session state. Any action method that is called after the TempDataDictionary value is set can get values from the object and then process or display them. The value of TempData persists until it is read or until the session times out.
This MSDN article explains it all.
I'm attempting to process the body of an HTTP PUT request, but it seems that the MVC engine (or perhaps the ASP.NET stack underpinning it) isn't automatically parsing & populating the request's Form collection with the body data.
This does work as expected when doing a POST.
Note that the request's InputStream property does contain the expected data, and obviously I can build my own key/value collection using that, however I would have expected PUT to work the same way as a POST.
Am I missing something here?
Example action method:
[AcceptVerbs(HttpVerbs.Put)]
public ActionResult Purchase(int id, FormCollection data)
{
// Do stuff with data, except the collection is empty (as is Request.Form)
}
Quote from the doc:
The Form collection retrieves the
values of form elements posted to the
HTTP request body, with a form using
the POST method.
So instead of using Request.Form I would recommend you writing a custom model class that will hold the request data and pass it as action parameter. The default model binder will automatically populate the properties from the key/values passed in the request stream:
[AcceptVerbs(HttpVerbs.Put)]
public ActionResult Purchase(MyCustomModel model)
{
// Do stuff with the model
}
Asp.net does not support PUT out of the box for custom requests. If you are using not the built in capabilities to generate the PUT url try adding X-HTTP-Method-Override with value of PUT in headers, form, or query string.
public ActionResult RenderMyThing(IList<String> strings)
{
return View("RenderMyView");
}
How do I pass in strings?
routes.MapRoute("MyRoute", "RenderMyThing.aspx", new { controller = "My", action = "RenderMyThing" });
Is there a way I could pass in strings here?
Secondly, how does ASP.NET MVC know that action is my action, and controller is my controller. Like I saw this in samples, and it does work, but isn't it just an anonymous object with no type?
This is the provenance of model binding: the framework needs to have some instruction as to how to turn a "request", which comes out of the routing context, query string, forms collection, etc., into the parameters that your action method wants.
The DefaultModelBinder will generate a list if it sees that you have multiple key-value pairs with the same key (and appropriately typed/convertible values) - for the details, Phil wrote a good post about this:
If you need fancier binding requirements, you can implement a custom model binder and explicitly define how route values and the other bits get translated into objects (or collections of objects).