No Body Data Being Passed using .NET CORE 6 - c#

I'm migrating my code from .NET to .NET Core 6 and have hit a brick wall and googling doesn't seem to have helped so any advice, pointers will be welcome.
All of this works in .NET so it's clearly my understanding of how to migrate the API.
I am using a greasemonkey script to scrape some data and pass it to my site.
function sendHome() {
console.log(window.eval('window.PA_intel'));
GM.xmlHttpRequest({
method: "POST",
url: "https://localhost:7223/api/Parsing/Any",
data: "{ Data: '" + JSON.stringify(window.eval('window.PA_intel')) + "', Type: 'Intel'}",
headers: { "Content-Type": "application/json" },
onload: function (response) { console.log(response); toastr["success"]("Intel sent home!", "Phoenix"); },
onerror: function (reponse) {console.log("error: ", reponse)},
});
}
This grabs the data from a page an pushes it to an API route that is waiting on api/Parsing/Any
The debug and postman can trigger the API controller so I know the routing works but the body (Data and Type from the GM script) isn't coming with it.
I have a defined model to receive the data
public class ParseData
{
public string Data { get; set; }
public string Type { get; set; }
}
and my controller is set up to expect it, but in .NET CORE 6 it's just coming up null
[Route("api/Parsing/")]
public class ParsingAPIController : Controller
{
[Route("Any")]
public List<ParseResult> ParseAny(ParseData parseData)
//public List<ParseResult> ParseAny(string Data, string Type)
{
As I said the routing is being triggered but the parseData object is null and if I inpsect ParseAny to see what has been sent, I get an error with null body.
Any ideas where I am going wrong?

Fix ajax data
...
data: JSON.stringify({ Data: window.eval('window.PA_intel'), Type: 'Intel'}),
...
and an action header
[Route("Any")]
public List<ParseResult> ParseAny([FromBody]ParseData parseData)

You can try using the tag [FromBody] with the ParseData parameter.

Actually you need to do 2 things:
Add [ParseBody] to your parameter.
Add [HttpPost] as annotation to your method so that it accepts post requests and gets the post body in the request. Finally your code should be like below:
[Route("api/Parsing/")]
public class ParsingAPIController : Controller
{
[Route("Any")]
[HttpPost]
public List<ParseResult> ParseAny([FromBody]ParseData parseData)
{

Related

Passing multiple parameters in Ajax Call with Razor

So essentially, I'm building a web API, and I'm trying to use ajax to query a web service that accepts two arguments. I need to pass a List of Stings (SSNs) and I need to pass a single string to determine which environment it queries. ("a" for acceptance, and "i" for integration).
I'm using cshtml with razor. And so far this section is successfully giving me what I want from the divs.
var pInputSssns = document.GetElementById(“SSNinput”).value;
var pTestRegion = document.GetElementById(“testRegion’).value;
However, just beneath it. I'm trying to insert both these params into an ajax call.
$.ajax({
type: 'GET',
contentType: "application/json; charset=utf-8"
url: "myurl",
data:"{}",
success: function (data) {
// populate a table
}
});
I've heard multiple opinions on how that can be done. Can I serialize them both as JSON, and then put two JSON objects in the data parameter? I've also heard that I can pass a c-sharp object, but if I try and do that I can't access the html variable while I'm inside the Razor code.
#{ AjaxParam ap = new AjaxParam(); ap.pInputSsns = pInputSsns;}
Is there a good way to pass both of them in there? For reference, here's the Controller:
[ScriptMethod (ResponseFormat = Response Format.Json)]
[System.Web.Http.HttpGet]
public JArray GetSSNAssociations([FromUri] List <string> pInputSsns, string pTestRegion)
{
\\ do something
}
Appreciate it everyone.
First, create a DTO class for the data you want to send.
public class SearchRequest
{
public List<string> SsnList { set; get; }
public string Environment { set; get; }
}
Now in your WebApi controller's Post method will have this class as the parameter so that when the client sends a request, the default model binder will be able to map the request values to the properties of an object of this class.
public class ProductsController : ApiController
{
public HttpResponseMessage Post([FromBody]SearchRequest req)
{
// I am simply returning the same object back. But you can do whatever you want
// Check req.SsnList and req.Environment properties and do something useful.
return Request.CreateResponse(HttpStatusCode.OK, req);
}
}
Now from the client side code, You can build a javascript object which resemebles the structure of our DTO class and send it using jQuery ajax.
var model = { Environment: "I", SssList: ["375329567", "3583345"] };
var url="../api/products";
$.ajax({
type: "POST",
data: JSON.stringify(model),
url: url,
contentType: "application/json"
}).done(function (res) {
console.log('res', res);
// Do something with the result :)
});
Here is a post explaining the different options to send client side data to web api in detail.
I hardcoded the value of url variable. You should consider using the Html helper methods like Url.Action to generate the correct relative path to your app endpoint as explained in this post.

Jquery ajax call to pass JSON array in MVC (500 internal server error)

Here is my ajax that is being invoked as a function when an array has data.
function sendDataToController() {
$.ajax({
type: 'POST',
url: '/Home/Results',
cache: false,
traditional: true,
contentType: "application/json",
data: { FormData : exampleFormData },
success: function (data) {
alert("sent data to controller")
},
error: function (data) {
alert("Error " + data.responseText);
}
});
}
The array looks like this:
var exampleFormData = [];
And the JSON looks like this currently with some more data but shortened for display purposes.
"[{\"Birthdate\":\"1947-03-21\",\"ROWID\":\"000001\",\"SpecCodes\":\"987654\"}]"
This JSON is being pushed into the array multiple times before using ajax to send to the controller.
exampleFormData.push(jsonData);
The control that this is being passed into looks like this:
public ActionResult Results(string exampleFormData)
{
var formDataList = JsonConvert.DeserializeObject<List<SampleFormData>>(exampleFormData);
return View();
}
And here is the class that models that "SampleFormData" list
public class SampleFormData
{
public string Birthdate { get; set; }
public string ROWID { get; set; }
public string Score { get; set; }
public string SpecCodes { get; set; }
}
As is, this produces a 500 internal server error. Can anyone provide any input on what is being done incorrectly here?
Edit: The solution for this was to remove the contentType line from ajax completely and was provided by Rion in the responses.
There are a few things to consider with the code you provided that could be causing your issue.
Ensuring You Can Post Properly
In order for your Controller to actually acknowledge the jQuery call, you'll need to ensure that the Controller Action is decorated with the [HttpPost] attribute, indicating it should be used for POST calls :
[HttpPost]
public ActionResult ExamineeResults(string exampleFormData)
{
// Your code here
}
Ensuring You Are Targeting The Proper Action
Your AJAX call currently is targeting Home/Results, however the name of your actual Controller Action is ExamineeResults. Unless you have some specific routing rules in place, you should use the existing name to make sure you target it correctly :
url: '/Home/ExamineeResults',
Additionally, if you have this within your View, you can use the Url.Action() method to resolve the proper location :
url: '#Url.Action("ExamineeResults","Home")'
Using Proper Parameters
MVC will only know how to properly map data as you specify it. Currently you are posting your contents as such :
data: { FormData : exampleFormData },
This means that the name of your parameter in your Controller Action should match that exactly (i.e. FormData instead of exampleFormData) :
public ActionResult ExamineeResults(string FormData)
Putting All Of These Together
You should be able to resolve this by updating your code as follows :
$.ajax({
type: 'POST',
// Use Url.Action() to resolve the proper URL
url: '#Url.Action("ExamineeResults","Home")',
cache: false,
// Use JSON.parse() to serialize your content to send accross
data: { formData: JSON.parse(exampleFormData) },
success: function (data) {
alert("sent data to controller")
},
error: function (data) {
alert("Error " + data.responseText);
}
});
along with the following Controller Action :
[HttpPost]
// You can let MVC perform the binding for your by mapping your content
// to an array of your SampleFormData objects
public ActionResult ExamineeResults(SampleFormData[] formData)
{
// Do your thing here (as formData is already serialized)
return View();
}
You can see an example of this here and demonstrated below :
One of the issue with this call could be the fact that you're returning a View to an ajax call. As far as I know, this is not possible. If you must post to this ActionResult you must do a post. Also, make sure your routing is correct. Running this code as is will not reach the desired endpoint as your ActionResult is named "ExamineeResults" and your url is "/Home/Results". Hope this helped.

Unable to post simple string data to Web API from AngularJS

I am trying to get a json string from my angular app to a Web API. I have looked all over the internet the past 6 hours trying and failing miserably to figure out what I am doing wrong.
I have checked the network console and I can see the json as form data, but my WEB api for some reason is NOT getting it. I have looked at several other posts but none seem to help with my particular issue. Any direction would be great. I already tried using the "transform" fix, but that didn't help.
ENTRY POINTS TO WEB API
[HttpPost]
[Route("api/SkeltaInterfaceController/SaveWorkflow")]
public bool SaveWorkflow([FromBody] string json)
{
...
}
ANGULAR CALL
$scope.SaveWorkFlow = function () {
$http({
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
method: "POST",
url: webAPI,
data: {'DATA' : 'TEST DATA'
}
})
}
EDIT: I changed the angular call to this
$scope.SaveWorkFlow = function () {
$http({
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
method: "POST",
url: webAPI,
data: {'DATA' : 'TEST DATA'}
})
}
The Web API looks like this
[HttpPost]
[Route("api/SkeltaInterfaceController/SaveWorkflow")]
public bool SaveWorkflow([FromBody] TestModel json)
{
...
}
And the model
public class TestModel
{
public string DATA { get; set; }
}
I am still getting a null value for DATA though, something I setup wrong?
Though you have got an solution, there are some ways to POST simple string data (not an object) to a Web API service.
Let's say you have a POST API like this (in Test ApiController)
public void Post([FromBody]string value)
{
//do something with value
}
From AngularJS you can post to this method like
(1) data as JSON (default)
$scope.Test = function () {
$http({
method: "POST",
url: "/api/Test",
data: JSON.stringify("test")
});
};
This will use Content-Type: application/json by default. And server will treat the data as JSON. If you look at the request, you'll see the request body is a simple string, like
"test"
For complex objects, you'd see them JSON formatted.
(2) data as application/x-www-form-urlencoded (as in your example)
$scope.Test = function () {
$http({
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
method: "POST",
url: "/api/Test",
data: $.param({ "": "test" }),
});
};
Here, we are explicitly specifying the content type to be application/x-www-form-urlencoded, so we have to send data in that format (much like url query string). And, here, the empty key in data is just to satisfy Web API's strange model binding requirement! The resulting data will be encoded like
=test
which we'have done with $.param({ "": "test" }). One reason for this, FromBody is used mainly to send object, not simple primitive values.
So, the basic problem with your code was, you had specified Content Type : application/x-www-form-urlencoded and you were sending the data as JSON!
I think your issue comes down to the WebApi controller method expecting to receive a string, but you are passing it an object. Is it at least hitting the method but receiving null?
It depends what you are trying to send to the WebApi controller method, but if you mean to send an object, you should create a model that represents that object in your WebApi project and have the method take an object as the parameter.
For example, the way you have it right now you would do something like:
public class SaveModel
{
public string DATA {get; set;}
}
[HttpPost]
[Route("api/SkeltaInterfaceController/SaveWorkflow")]
public bool SaveWorkflow([FromBody] SaveModel model)
{ ...

Asp.net Web API Post List<t> Not Getting Inside Method

I am running into a problem where I can't seem to pass this data properly from jquery to the web api.
Here is my javascript code:
var chartRequestParams = [
{ QueueMode: "Investigations", DataMode: "items_completed" },
{ QueueMode: "Investigations", DataMode: "items_completed_avg_age" },
{ QueueMode: "Investigations", DataMode: "active_items" }
];
$.post('/api/dashboard/GetActiveAgeChart', chartRequestParams, function (data) { });
Here is my Web API Code:
[HttpPost]
public List<HighChartsResponse> GetActiveAgeChart(List<ChartRequestParam> chartRequestParams)
{ .....continued....
It's not even making it into the above method
Here is my "model"
public class ChartRequestParam
{
public ChartRequestParam()
{
this.QueueMode = string.Empty;
this.DataMode = string.Empty;
}
public string QueueMode { get; set; }
public string DataMode { get; set; }
}
I've tried soooo many variations of this code with no success. Basically I'm just trying to post a List to the web API method.
I receive a 500 server error, and it if i set a breakpoint inside the "GetActiveAgeChart" method it doesn't even hit it.
First, I assume your controller is named DashboardController. If so, you will need to post to /api/dashboard without the action method in the URI. Web API does support RPC-style but it is not probably important for this.
Second, you will need to stringify the payload, something like this.
$.ajax({
url: '/api/dashboard', type: 'POST', contentType: 'application/json',
data: JSON.stringify(chartRequestParams)
});
This will post the request message as JSON. If you prefer it to be www-form-urlencoded, you will need to read http://aspnetwebstack.codeplex.com/workitem/177.

What parameter does my .NET MVC 2 controller need for a JSON Post

I can't figure out what parameters or type to use in my controller when accepting a POST from an .ajax jquery call which is using Json.
The JSON looks something like this (I just wrote this so it might not be valid, that's not the problem)
[{"paths":[[{"a":294,"b":174,"c":1297178158028}]]
My controller:
[HttpPost]
public void SaveDrawData() {
}
$.ajax('../Home/SaveDrawData', { type: 'POST', contentType: 'application/json', dataType: 'json', processData: false, cache: false, data: serial, success: function() { var saved = $('<div id="saved">Saved!</div>')
.appendTo('body')
}
I know for sure that the SaveDrawData is being hit by setting a breakpoint.
I checked firebug, and the JSON post lists "paths".
How does my controller access that data though? What type and/or variable name do I need to put there?
Thanks so much!
Have you tried:
public ActionResult SaveDrawData(string paths)
{
//do stuff here
}
Also try to access ViewData["paths"] in your controller action. If you add attach the debugger and Add Watch for ViewData, you should be able to see what the view is sending back and what it is calling it.
What about this solution
html code:
<% using (Ajax.BeginForm(new AjaxOptions(){UpdateTargetId =
"location", HttpMethod = "POST"})){ //do your stuff here} %>
controller
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult YourAction()
{
IList<KeyValuePair<string, object>> results = new
List>();
KeyValuePair<string, object> pair1 = new
> KeyValuePair<string, object>("key one",
>
> new {testing = "object one testing "});
> results.Add(pair1);
> //return Json(results, JsonRequestBehavior.AllowGet);
> //if you want allow get
> return Json(results);
> }
where when submit happenes:
there will be request as when you sending html form and you will get results accesible as Request["parameterName"]
or bind it to the model where you will put the model to action of the controller:
EG:
public ActionResult YourAction(FooModel model){
//do your thing
}
To read about this, visit this tutorial..
http://lozanotek.com/blog/archive/2010/04/16/posting_json_data_to_mvc_controllers.aspx
I hope this will help.
You can pass an array as a POST parameter, and MVC will detect it as a List of strings.
[HttpPost]
public ActionResult SaveDrawData(List<string> paths)
{
var someObject = CreateObjectFromPaths(paths);
return Json(someObject);
}
Also, on your $.ajax jQuery call, try setting traditional: true
UPDATE
I looked more closely at what you're passing into the .ajax call. Looks like your parameter would actually be a List<int> :)
Since you are using MVC 2, you need to reference ASP.NET MVC Futures to receive JSON values. Make sure first that your controller has ASP.NET MVC Futures, then try to JSON-post simple(e.g. integer) types to your controller method as POC that your controller can already receive JSON data; if you've verified your controller can already receive JSON data, then try this structure:
public class Mate
{
public int a { get; set; }
public int b { get; set; }
public int c { get; set; }
};
public void SaveDrawData(Mate[] paths) {
}
JSON-library for ASP.NET MVC 2: ASP.NET MVC Futures: http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx

Categories

Resources