Passing dictionary to REST API - dictionary

I need to POST a key pair value dictionary to the REST API. I am using NancyFx framework for binding parameters
Server side property:
public Dictionary<string, string> foo { get; set; }
Client side code:
var bar = [];
bar["one"] = "First";
bar["two"] = "Second";
var UserModel = {
someotherpar: "abc",
foo: bar
};
$.ajax({
url: 'myEndpoint',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(UserModel),
success: function (data, textStatus, jqXHR) {
}
});

This was possible with the use of SortedList and not Dictionary.

Related

Why ajax send parameters to controller is null?

I sending a post request to controller by ajax:
This is my code in cshtml file:
<script>
$("#btnSeachAjax").click(function () {
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
url: '#Url.Action("Search")',
data: { id: "1",title:"ba"},
contentType: 'application/json',
type: 'POST',
headers: {
"RequestVerificationToken": token
},
success: function (data) {
$("#data").html(data);
}
,
error: function (req, status, error) {
alert(error);
}
});
return false;
});
</script>
This is my code in controller:
[HttpPost, ActionName("Search")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Search([FromBody] string id,string title)
{
var movie = await _context.Movies.FindAsync(id);
return View(movie);
}
Value of id , title in controller = null.
Why ajax send parameters to controller is null?
I using Asp.net mvc net core 3.1.
public async Task<IActionResult> Search([FromBody] string id,string title)
Value of id , title in controller = null.
Based on your action method and accepted parameters, you can try to modify the Ajax code as below.
$.ajax({
url: '#Url.Action("Search")'+'?title=ba',
data: JSON.stringify("1"),
contentType: 'application/json',
type: 'POST',
//...
Besides, you can create a viewmodel and modify your action accept a complex type parameter, like below.
public class MyData
{
public string Id { get; set; }
public string Title { get; set; }
}
Action method
public async Task<IActionResult> Search([FromBody] MyData myData)
{
//...
On JS client side
$.ajax({
url: '#Url.Action("Search")',
data: JSON.stringify({ id: "1", title: "ba" }),
contentType: 'application/json',
type: 'POST',
//...

pass string array as parameter to asp.net mvc webapi method

I am using webapi2 and here is my client side code
var tbody = $('#files-table').find('tbody'); // tbody where all rows exists
var sortOrder = $(tbody).sortable('toArray').toString(); // geting ids of all rows
var updateSortOrder = $.ajax({
url: baseUrl + 'mycontroller/updateimagesorder',
dataType: 'json',
traditional: true,
contentType: 'application/json',
data: JSON.stringify({ "sortOrder": sortOrder.split(',') }),
type: 'PUT'
});
updateSortOrder.done(function (result) {
closeModel('images-model');
});
and here is my server side method
[Route("updateimagesorder")]
public HttpResponseMessage PutImagesSortOrder([FromBody]string[] sortOrder)
{
// do stuff with parameters
}
Note : /mycontroller is route prefix here and baseUrl is my domain url
so , what the issue in my code ?
Try passing the value like this:
data: JSON.stringify(sortOrder.split(',')),
So that your request payload looks like a string array:
["foo", "bar"]
If you want to pass the value like that:
data: JSON.stringify({ "sortOrder": sortOrder.split(',') }),
then make sure that you have declared a view model:
public class MyViewModel
{
public string[] SortOrder { get; set; }
}
that your controller action will take as parameter:
[Route("updateimagesorder")]
public HttpResponseMessage PutImagesSortOrder(MyViewModel model)
{
// do stuff with parameters
}

How to handle FormData AJAX post (file with additional params) with asp.net WebMethod

Having trouble handling a jQuery AJAX post of FormData to an ASP.net 4 Web service WebMethod.
<input id="ipt_file" type="file" />
<a href='#' onclick="UploadFile();" data-role='button'>Upload</a>
var UploadFile = function () {
var file_object = $('#ipt_file')[0].files[0];
var form_data = new FormData();
form_data.append('job_id', '123456');
form_data.append('job_name', 'xyx');
form_data.append('job_file', file_object);
var xhr_upload = $.ajax({
type: "POST",
headers: { "Cache-Control":"no-cache", "Content-Type":"multipart/form-data" }, // also tried without these
url: "../MyServices.asmx/Upload",
data: form_data,
processData: false,
contentType: false,
dataType: "json",
success: function (msg) {
if (typeof (msg) === "object") {
var _upload = $.parseJSON(msg.d);
alert(_upload.status + ': ' + _upload.msg);
};
}
});
};
public class FileUploadRequest
{
public string job_id { get; set; }
public string job_name { get; set; }
public HttpPostedFile job_file { get; set; }
}
[WebMethod]
public string Upload(FileUploadRequest x)
{
string str_response = string.Empty;
if (x.job_file.ContentLength > 0)
{
str_response = "{\"status\":1,\"msg\":\"" + x.job_id + ", " + x.job_name + ", " + x.job_file.FileName + "\"}";
}
else
{
str_response = "{\"status\":0,\"msg\":\"FAIL"\}";
};
return str_response;
}
Must not be handling the FormData object parameter properly; here I instantiated a custom class, but all I get back from the server is 500 errors (also tried a generic object x). Also tried handling it as HttpRequest object as I've seen on some postings, to no avail. Not concerned about IE 9 incompatibility in this case; just want to see single file upload or at least a FormData object with key/value pairs properly received by an asmx WebMethod.
I did get it to work with the following code, in case anyone wants to see it:
var upload_file = $('#ipt_file')[0].files[0];
var upload_filename = upload_file.name;
var upload_maxsize = 10485760;
var upload_projectname = "test";
var form_data = new FormData();
form_data.append('session_id', this.sessionID());
form_data.append('project_name', upload_projectname);
form_data.append('file_name', upload_filename);
form_data.append('file_size', upload_file.size);
form_data.append('file', upload_file);
if (upload_file.size < upload_maxsize) {
var xhr_upload = $.ajax({
type: "POST",
headers: { 'Cache-Control': 'no-cache' },
url: "../services/upload.ashx",
data: form_data,
processData: false,
contentType: false,
dataType: "json"
}
})
.done(function (xhr_data) {
...
})
.fail(function (jqXHR, textStatus, errorThrown) {
...
})
.always(function () {
...
});
.NET will not allow the multipart/form-data for the content-type:
JSON Hijacking and How ASP.NET AJAX 1.0 Avoids these Attacks
There is a built-in validation layer of protection that ASP.NET
enforces for both GET and POST based ASP.NET AJAX web methods, which
is that regardless of the HTTP verb being used, ASP.NET always
requires that the HTTP Content-Type header is set to the value
application/json. It this content type header is not sent, ASP.NET
AJAX will reject the request on the server.

Web Api Parameter always null

Why is the parameter always null when I call the below Post method with the below ajax?
public IEnumerable<string> Post([FromBody]string value)
{
return new string[] { "value1", "value2", value };
}
Here is the call to the Web API method via ajax:
function SearchText() {
$("#txtSearch").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "api/search/",
data: "test",
dataType: "text",
success: function (data) {
response(data.d);
},
error: function (result) {
alert("Error");
}
});
}
});
}
$.ajax({
url: '/api/search',
type: 'POST',
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
data: '=' + encodeURIComponent(request.term),
success: function (data) {
response(data.d);
},
error: function (result) {
alert('Error');
}
});
Basically you can have only one parameter of scalar type which is decorated with the [FromBody] attribute and your request needs to use application/x-www-form-urlencoded and the POST payload should look like this:
=somevalue
Notice that contrary to standard protocols the parameter name is missing. You are sending only the value.
You can read more about how model binding in the Web Api works in this article.
But of course this hacking around is a sick thing. You should use a view model:
public class MyViewModel
{
public string Value { get; set; }
}
and then get rid of the [FromBody] attribute:
public IEnumerable<string> Post(MyViewModel model)
{
return new string[] { "value1", "value2", model.Value };
}
and then use a JSON request:
$.ajax({
url: '/api/search',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ value: request.term }),
success: function (data) {
response(data.d);
},
error: function (result) {
alert('Error');
}
});
You cannot use a simple type for the [FromBody] attribute with the JSON content type. Although the default in Visual Studio has a string from body this is for the application/x-www-form-urlencoded content type.
Put the string value as a property on a basic model class and the deserialiser will work.
public class SimpleModel()
{
public string Value {get;set;}
}
public IEnumerable<string> Post([FromBody]SimpleModel model)
{
return new string[] { "value1", "value2", model.Value };
}
Change the JSON you are sending to:
{"Value":"test"}
whenever we are calling web api action and which take [frombody] parameter then input parameter prefix with =
for example
public string GetActiveEvents([FromBody] string XMLRequestString) {
}
to call above web api action
URI
2.
User-Agent: Fiddler
Content-Type: application/x-www-form-urlencoded
Host: localhost:54702
Content-Length: 936
request body is =data
I hope this will give clear idea.
I've just had a beast of a time with this and .NET Core Web API. So hopefully to save time for someone: The actual problem for me was simple - I wasn't converting to the correct type (Notice #Darins answer uses a VM rather than a string).
The default type in the template is string. I thought because we're sending stringified JSON, we would see a JSON string, but this was not the case. I had to make it the correct type.
E.g. This failed
[EnableCors("AllowAll")]
[HttpPost]
public HttpResponseMessage Post([FromBody]string value)
{
// Do something with the blog here....
var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
return msg;
}
But this worked.
[EnableCors("AllowAll")]
[HttpPost]
public HttpResponseMessage Post([FromBody]Blog value)
{
// Do something with the blog here....
var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
return msg;
}
Ajax Call
function HandleClick() {
// Warning - ID's should be hidden in a real application
// - or have covering GUIDs.
var entityData = {
"blogId": 2,
"url": "http://myblog.com/blog1",
"posts": [
{
"postId": 3,
"title": "Post 1-1",
"content": "This is post 1 for blog 1",
"blogId": 2
},
{
"postId": 4,
"title": "Post 1-2",
"content": "This is post 2 for blog 1",
"blogId": 2
}
]
};
$.ajax({
type: "POST",
url: "http://localhost:64633/api/blogs",
async: true,
cache: false,
crossDomain: true,
data: JSON.stringify(entityData),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (responseData, textStatus, jqXHR) {
var value = responseData;
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});
}

Asp.net Mvc Ajax Json (post Array)

javascript\jQuery:
var items = new Array();
var obj { Begin: "444", End: "end" };
items.push(obj);
items.push(obj);
var request = {
DateStart: $("#DateStart").val(),
mass: items
};
$.post("/Home/Index", request, null,
"json");
C# Mvc Index Controller
public class MyClass
{
public string Begin;
public string End;
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(
string DateStart,
MyClass []mass)
{
System.Diagnostics.Debug.WriteLine(mass[0].Begin);
}
how to execute this code? thanks.
U can't pass mass: items and expect it to be serialized as a JSON array automatically, you will need to either iterate and construct the JSON (bad plan) or use a JSON library(good plan)
Try write code as below:
var option = {
url: '/Home/Index',
type: 'POST',
data: JSON.stringify(request),
dataType: 'html',
contentType: 'application/json',
success: function(result) {
alert(result);
}
};
$.ajax(option);

Resources