Web Api, ajax and Content Type - c#

I would like to understand a little better about WebApi in Net and how is the correct way to called it with ajax. Little of info about my development environment: I am using .net 4.0 and visual studio 2010 and Jquery.
Model:
public class TestForm
{
public string FirstName { get; set; }
}
WebApi:
public class TestpController : ApiController
{
[HttpPost]
public HttpResponseMessage Post(TestForm form)
{
string jose = "jose";
return Request.CreateResponse(HttpStatusCode.OK, "yay");
}
}
Client side:
V1 (doesnt work, return error 405 ):
$.ajax({
url: "http://xxx/api/Testp",
type: "POST",
data: JSON.stringify({ FirstName: "Jose" }),
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function(data) {
console.log("success");
},
error: function (xhr, errorType, exception) {
console.log("error");
}
});
V2 (works):
$.ajax({
url: "http://xxx/api/Testp",
type: "POST",
data: { FirstName: "Jose" },
dataType: 'json',
success: function(data) {
console.log("success");
},
error: function (xhr, errorType, exception) {
console.log("error");
}
});
Why do I get an error when I add contentType: "application/json; charset=utf-8" and change the data to JSON.stringify({ FirstName: "Jose" }), but it works when I removed the content type and send a object in data option.

Short answer lies in the output of these alerts:
alert(JSON.stringify({FirstName :"Jose"}));
alert({FirstName :"Jose"});
The first one gives you a string, the second one gives you an object.
Your method:
public HttpResponseMessage Post(TestForm form)
Accepts an object and not a string. So when you post a string, .NET Framework is not able to find a method which can process a string, hence returns 405.

The Problem you are encountering seems to be jQuery preflight.
If you take a look at the Headers of your request you'll see that in V1 the Http Method used is actually OPTIONS. That is because jQuery does only allow certain values for the Content-Type Header.
#McBoman gave a good overview on this, at the linked source. You may also want to read up on Cross Origin Resource Sharing (Cors) for example this.
You need to add a Function that answers to [HttpOptions] and explicitly tells the preflight-request that a certain "custom"-Header is allowed or in the case of cross-origin request allowing the originating domain.
You would need to adapt the below Function to your needs, taking the info preflight provides you with.
[HttpOptions]
public HttpResponseMessage Options() {
var response = request.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("access-control-allow-origin", "*");
response.Headers.Add("access-control-allow-headers", "content-type");
return response;
}
Hope that helps you.

Related

ASP.NET Core jQuery POST - Incorrect Content-Type despite correctly formatted headers

I have researched similar threads, such as this one and this one, and have determined that this deserves its own thread, as I could not find any help in an hour of research.
I am trying to send a POST request to an ASP.NET Core host from a jQuery request. This is how I've formatted my POST request in the frontend:
$.ajax({
url: "/Merge",
type: "POST",
contentType: 'application/x-www-form-urlencoded',
datatype: "json",
data: {
"example": "examplecontent"
},
success: function (data) {
alert(data);
}
});
This is the way I'm ingesting it in the backend for testing purposes:
[HttpPost]
public IActionResult Index()
{
var x = HttpContext.Request.Form;
Dictionary<string, string> exampleDict = new();
//exampleDict.Add("Testing", HeaderElem);
JsonResult result = new(exampleDict);
return result;
}
Despite including complete headers, I have been getting this error on the backend claiming that I have an 'incorrect content type':
What might be wrong with my request?
you have to fix the action
[Route("~/Merge")]
public IActionResult Index(string example)
{
return Ok ( new { example = example } );
}

ajax POST sending null

I originally wrote the call as a GET but found a limitation with the length of the URI. Ideally, the call will take an object and turns it into a JSON format string, then sends it to a controller which will encrypt that string. The controller will send back a true/false if it succeeded.
My problem with POST, once it reaches the controller, the data parameter set from the ajax is null.
Here is the ajax/js:
var encActionURL = '#Url.Action("Encrypt", "Home")';
$.ajax({
url: encActionURL,
type: "POST",
contentType: "application/json; charset=utf-8;",
dataType: "json",
async: true,
traditional: true,
data: { jsonDoc: JSON.stringify(jsonDataFile) },
success: /*OnSuccess*/ function (result) {
// DO STUFF;
}
});
Here is the controller:
[HttpPost]
public bool Encrypt(string jsonDoc)
{
return serverConnection.Encrypt();
}
Note that, when I simply change the type to 'GET', it works great but when the form gets too long, it throws a 414 status error.
Most of the fixes found that I seem to have is the 'application/json'. I've also set ajax to traditional.
After going through a rabbit-hole of security tokens and validating forms, it wasn't any of that... this might be a solution for anyone using ASP.NET Core 2.1 MVC (5?) or just in general. Could have been a syntax mistake, return type mistake, or a combination.
New Ajax
$.ajax({
url: encActionURL,
type: "POST",
data: { 'jsonDoc': JSON.stringify(jsonDataFile) }, // NOTICE the single quotes on jsonDoc
cache: false,
success: /*OnSuccess*/ function (result) {
// DO STUFF;
}
});
New Controller
[HttpPost]
public ActionResult EncryptJSON(string jsonDoc) // Switch to ActionResult, formerly JsonResult
{
return Json(serverConnection.Encrypt());
}

Ajax error when there's a parameter in url

I have a ajax code that fills a dropdownlist and I use mvc c#.
When I call to my method from ajax and I have an url in the directions bar without parameters the code works correctly, but if I have a parameter in url in the directions bar this not working and appears this error:
"{readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}".
Here's my code:
$.ajax({
url:"../Records/myList",
type: "POST",
dataType: 'json',
contentType: 'application/json',
// data: JSON.stringify(Data),
success: function (resul) {
Function(resul);
},
error: function (message) {
}
});
My url: http://localhost:123/Record/EditRecord ->> so it's works
My other url: http://localhost:123/Record/EditRecord/1 ->> It does not work like this
Thanks in advance.
From given second URL (which doesn't work) I assume that you want to use jQuery AJAX with HttpGet method. The URL pattern matches this route:
http://localhost:123/{controller}/{action}/{id}
which id treated as UrlParameter.
Hence you need to use action argument & data representing URL parameter values, like this example:
Controller
[HttpGet]
public ActionResult EditRecord(int id)
{
// other stuff
}
View (JS)
$.ajax({
url: "/Record/EditRecord",
type: "GET",
dataType: 'json', // response type
contentType: 'application/x-www-form-urlencoded; charset=utf-8', // header content type
data: { id: 1 },
processData: true, // this is important to use in GET methods
success: function (result) {
Function(result);
},
error: function (message) {
// throw error
}
});
Alternatively a direct usage of URL parameter is applicable for GET methods without specifying data content:
View (JS)
$.ajax({
url: "Record/EditRecord/1",
type: "GET",
processData: true, // this is important to use in GET methods
success: function (result) {
Function(result);
},
error: function (message) {
// throw error
}
});
NB: Use jQuery.get for simplified version:
$.get("/Record/EditRecord/1", function (result) {
Function(result);
}, "json").error(function (message) { // throw error
});
PS: This is an example for HTTP POST request if you're looking for proper POST method with AJAX.
Controller
[HttpPost]
public ActionResult EditRecord(Record rec)
{
// other stuff
}
View (JS)
$.ajax({
url: "/Record/EditRecord",
type: "POST",
dataType: 'json', // response type
contentType: 'application/json; charset=utf-8', // header content type
data: JSON.stringify({ rec: { id: 1, name: 'XXXX', ... }}),
success: function (result) {
Function(result);
},
error: function (message) {
// throw error
}
});
Reference:
Do GET, POST, PUT, DELETE in ASP.NET MVC with jQuery AJAX
i cant see any fault in the code but i suggest to try let the param come with it's name at server either if you choose to use data propery (of ajax function):
{key1: 'value1', key2: 'value2'}
or you use string query:
page?name=ferret&color=purple
bacuse you've just say that first method was work i assume there is no need to check POST/GET method.
EDIT:
be award to this.

Ajax Webmethod not being called

I make a total of four Ajax calls in my .NET application. Three of them work without a hitch except the last one.
Note: I HAVE to use .aspx for these calls and not mypage.aspx/mymethod because of our architectural constraints.
Ajax call that works:
$.ajax({
type: "POST",
url: "myaddress/GenerateOpinionHTML.aspx",
data: JSON.stringify({ id: featureId, pageNumber: pageNumberIndex }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
SOME PROCESSING (IT WORKS)
},
error: function (xhr, status, error) {
var err = xhr.responseText;
console.log(err);
}
});
and
[WebMethod]
public static string GenerateOpinionHTML(int id, int pageNumber)
{
// ...
}
Ajax call that does not work:
console.log("SUBMITOPINIONCLICK");
var param = " ";
$.ajax({
type: "POST",
url: "myaddress/SaveOpinion.aspx",
data: JSON.stringify({ parameter: param}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log("SAVE OPINION SUCCESSFUL");
console.log(msg.d);
CloseLB('GiveOpinionLB');
},
error: function (xhr, status, error) {
var err = xhr.responseText;
console.log("ERROR " + "STATUS: " + status);
}
});
and
[WebMethod]
public static string SaveOpinion(string parameter)
{
// ...
}
The web method SaveOpinion is never called according to the logs. Do you have any ideas or suggestions? I tried adding parameters, without parameters, checking my web.config file (though I shouldn't have since the other calls work)...
The error I get on the browser console is a "parseerror". I'm certain I wouldn't be getting an error if the method was called.
I think your URL should be like
url: "Your FolderName/PageName/Function Name",
Like
url: "myaddress/SaveOpinion.aspx/SaveOpinion"
but in your code this is different so that please check.
Have you checked if method SaveOption return something to the client?
If you specify dataType as json, you should return (at least): {}
Ok so we "solved" it. We just found a very dirty band-aid workaround that works.
We made a custom handler (.ashx) that we defined in our architecture as a SaveOpinion.aspx page.
We then called this custom handler page with jQuery and voilà it works, we had to obviously pass all necessary parameters manually, ie. fetching all values from textBoxes etc with jQuery and not from the context as we did before.
Since this is run in some sort of thread (I don't really know the details) we had to configure it so that it simulates the same user authentification.
Anyway I hope this provides some measure of guidance for those with this kind of obscure problems.

ajax call to c# mvc sends both post and get

I've looked at several solutions for making an ajax call and by not this issue mentioned anywhere i feel it might be something specific to the environment i'm working with.
My controller:
[HttpPost]
public ActionResult ChangeDefualtCC(string a)
{
return Json("ok");
}
[HttpGet]
public ActionResult ChangeDefualtCC()
{
return Json("ok");
}
JS:
$("nevermind").change(function () {
$.ajax({
type: "POST",
url: "/Account/ChangeDefualtCC",
dataType: "json",
data: {
a: "A"
},
success: function (data) { console.log(data)},
error: function (data) { console.log("error");}
});
});
The Controller code is never hit, and this is what i'm seeing in chrome after the ajax call:
EDIT 2: The page hits the [HttpGet] method.
EDIT:
I tagged Ektron as well because it is used in the project, and it is possible that it is affecting the call.
My Routes:
Update: I have tried using Get, as well as Post, and also returning back to the View I was in, I get the 302 everytime.
any ideas?
It looks like it finds the "get" because you don't have a parameter in that call. I think you might be missing the content type from your ajax call, so the model binder cannot parse the content of your post as a parameter.
$.ajax({
type: "POST",
url: "/Account/ChangeDefualtCC",
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: {
a: "A"
},
success: function (data) { console.log(data)},
error: function (data) { console.log("error");}
});
Your code seems to be absolutely correct.
This not be exact solution but try this may it work.
$("nevermind").change(function () {
$.post("/../Home/ChangeDefualtCC", { a: "A" }, function (data) {
console.log(data)
});
});
Our project is integrated with the CMS Ektron. We later discovered that Ektron is hit before the C# code, and has some affect to any url without a trailing url.
Thanks for all the help

Categories

Resources