web api put is recognizing query strings but not body - c#

when i pass in users as a query string (using params in $http) and set the web api method to look for them in the uri everything is peachy. but when i pass them in as below, users shows up as null. what am i missing here?
angular function
scope.saveChanges = function () {
// create array of user id's
var users = [];
angular.forEach(scope.usersInRole, function (v, k) {
users.push(v.Key);
});
var data = { user: users };
var token = angular.element("input[name='__RequestVerificationToken']").val();
// put changes on server
http({
url: config.root + 'api/Roles/' + scope.selectedRole + '/Users',
method: 'PUT',
data: data,
contentType: "application/json; charset=utf-8",
headers: { "X-XSRF-Token": token },
xsrfCookieName: '__RequestVerificationToken'
}).success(function (result) {
// notify user changes were saved
angular.element('#myModal').reveal({ closeOnBackgroundClick: false });
});
};
web api action
public HttpResponseMessage Put(HttpRequestMessage request, [FromUri]string role, [FromBody]string[] user)
{
return request.CreateResponse(HttpStatusCode.NoContent);
}

Try: data: users instead of data: data.
In asp.net api, the whole request body is bound to a parameter. For this reason, you cannot have multiple parameters with the [FromBody] in the action method parameters. There is only one => we don't need to specify a property name in the request body.

Related

How to pass data from a controller to view during a JQuery AJAX call in MVC?

In my view, I have an AJAX call which sends an id parameter to my controller. This bit works fine. In my controller, I plan to query the database with that id, pull out associated data and want to send this back to the AJAX call/view. This is the bit I am struggling with, as I am new to AJAX calls.
var chosenSchoolID = $("#SelectedSchoolId").val();
$.ajax({
url: "/Home/GetSchoolDetailsAJAX",
type: "POST",
data: {
schoolID: chosenSchoolID
},
dataType: "text",
success: function(data) {
if (data == "success") {
}
},
error: function(data) {
if (data == "failed")
alert("An error has occured!");
}
});
The above is my AJAX call, and this does hit my controller method. However in my controller, I want to now send back other string data and I am unsure on how to do this (just placeholder code currently)
[HttpPost]
public ActionResult GetSchoolDetailsAjax(string schoolID)
{
// query database using schoolID
// now we have other data such as:
string SchoolName = "";
string SchoolAddress = "";
string SchoolCity = "";
return null;
}
Must I declare variables in my Jquery and pass into the data parameter of the AJAX call in order for the values to be passed?
Many thanks in advance
The simplest way to do this is to return the entities retrieved from your database using return Json() from your controller.
Note that when retrieving data then a GET request should be made, not a POST. In addition the default MVC configuration should have the routes setup to allow you to provide the id of the required resource in the URL. As such, try this:
$.ajax({
url: "/Home/GetSchoolDetailsAJAX/" + $("#SelectedSchoolId").val(),
type: "get",
success: function(school) {
console.log(school);
},
error: function() {
alert("An error has occured!");
}
});
[HttpGet]
public ActionResult GetSchoolDetailsAjax(string id) {
var school = _yourDatabaseContext.Schools.Single(s => s.Id == id); // assuming EF
return Json(school);
}
If you'd like to test this without the database integration, amend the following line:
var school = new {
Id = id,
Name = "Hogwarts",
Address = "Street, City, Country"
};

Passing String into an API method with a Route Attribute

I have a method on an API Controller where I've set the route in an attribute, but I don't seem to be able to pass a string into this. When I try to hit this with an Ajax Request from the browser the console shows the following error:
BAD REQUEST - The request could not be processed by the server due to
invalid syntax.
The string I'm passing over is huge, but unfortunately is the only way I can import the data into the legacy application I'm working with. The test URL I'm using is (brace yourselves):
http://localhost:50915/api/job/import/ALMIG&sup3123456&sup32%20DAY%20ECONOMY&sup320170720&sup320170721&sup30&sup3&sup3&sup3&sup322&sup3Lara%20Croft%20Way&sup3Derby&sup3&sup3&sup3DE23%206GB&sup3Stuff&sup310&sup31&sup30&sup325&sup30&sup3&sup31%7CI%20Great%20Danger&sup30&sup30&sup30&sup3&sup3&sup30&sup3true&sup30&sup3&sup3&sup3&sup3&sup3&sup3&sup31&sup30&sup30&sup316&sup3Baden%20Road&sup3Stoke-on-Trent&sup3&sup3&sup3ST6%201SA&sup3&sup30&sup30&sup30&sup3&sup3&sup3&sup30&sup30&sup30&sup30&sup3&sup30&sup31&sup30&sup3&sup3&sup3&sup3&sup3&sup3&sup3&sup3&sup3&sup3&sup3Liane&sup307730044916&sup3Lara&sup307730044916&sup30&sup3d2f0acf7-50e1-4a53-96ce-4fffd00b1a96&sup30
And the method is defined as below, the code inside is irrelevant as I put a break point on the start of the method which is never hit:
[System.Web.Http.HttpPost]
[System.Web.Http.Route("api/job/import")]
public int TmsImport([FromBody]string import)
{
// do something...
}
Edit: Added Ajax Request
job.confirmBookings = function () {
// TMS Import
job.toConfirmRow.filter(function(obj) {
var jobRow = obj;
var strArray = [];
for (var prop in jobRow) {
if (jobRow.hasOwnProperty(prop)) {
strArray.push(jobRow[prop]);
}
}
var joinedStr = strArray.join(job.seperator);
$.ajax({
type: "POST",
crossDomain: true,
data: joinedStr,
url: job.tmsString,
contentType: "application/json;charset=utf-8",
success: function (data, status, xhr) {
console.log("TMS ID: " + data + " | " + status);
},
error: function (xhr) {
alert(xhr.responseText);
}
});
});
First format the route template correctly
[HttpPost]
[Route("api/job/import")] //Matches POST api/job/import
public int TmsImport([FromBody]string import) {
// do something...
}
Also you should post the data in the body of the request. If the payload is large then you do not want that in the URL

Asp Mvc 5 Post to Odata never init data

I have created from wizard Asp Mvc 5 solution with Odata service to EF 6.
I want to send post request and create a record in database
but odata controller ran request, but not map JSON to EF object
what is wrong with my ajax request ?
Odata Method:
// POST: odata/SchoolChildrens
public async Task<IHttpActionResult> Post(SchoolChildrens schoolChildrens)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.SchoolChildrensSet.Add(schoolChildrens);
await db.SaveChangesAsync();
return Created(schoolChildrens);
}
JavaScript object Side (not all DB property here no need on client side):
var children = function () {
var self = this;
self.Id = ko.observable(0);
self.FullName = ko.observable();
self.IsPrivilege = ko.observable(false);
self.UseInShortMenu = ko.observable(false);
}
part of code that sent request, both case can't init data
self.addItem = function () {
var newStudent = ko.toJSON(self.newRow());
$.post("/odata/SchoolChildrens", JSON.stringify(newStudent), function (result) {
self.childrenList.push(result.value);
}).fail(function () { console.log("Function : Add SchoolChildrens error"); });
$.ajax({
type: "POST",
url: "/odata/SchoolChildrens",
data: newStudent,
success: function(result) {
self.childrenList.push(result.value);
},
dataType: 'json',
contentType: 'application/json'
});
};
I tried send JSON {schoolChildrens : ko.toJSON(self.newRow())} for map variable name but it also failed.
How I should send post request to odata controller correctly ?
Firstly, check if your request really contains any data (request object from page contains not null or undefined data property)
Second, when you use http methods that can send data in request body (POST, PUT, DELETE), it is necessary to add [FromBody] attribute before object as you want to map as method argument

How to obtain checked checkbox values on the serverside in c# from an ajax Http POST using web forms (not MVC)?

Here's my ajax call:
$(function () {
$("#chkFilter").on("click", "input", function (e)
{
var filterCheckboxes = new Array();
$("#chkFilter").find("input:checked").each(function () {
//console.log($(this).val()); //works fine
filterCheckboxes.push($(this).prop("name") + "=" + $(this).val());
console.log($(this).prop("name") + "=" + $(this).val());
//var filterCheckboxes = new Array();
//for (var i = 0; i < e.length; i++) {
// if (e[i].checked)
// filterCheckboxes.push(e[i].value);
//}
});
console.log("calling ajax");
$.ajax({
url: "/tools/oppy/Default",
type: "POST",
dataType: "json",
data: { filterValues: filterCheckboxes }, // using the parameter name
success: function (result) {
if (result.success) {
}
else {
}
}
});
});
});
And my server side code:
public partial class tools_oppy_Default : System.Web.UI.Page
{
...
protected void Page_Load(object sender, EventArgs e)
{
if (Request.HttpMethod == "POST")
{
string checkedBoxes = Request["filterValues"];
testLabel.Text = checkedBoxes;
}
I'm just trying to obtain the post URL with the appropriate checked values so I can parse it on the server. However, I'm having trouble obtaining the URL. The string checkedBoxes is supposed to hold a query string like name=value&name=value&name.... but when I test it, the testLabel doesn't show anything. I'm using web forms app, not MVC. Also, I'm new to ajax and their behavior. Thanks.
First, I assume that the url in you JQuery call is valid as there is not aspx extension their.
Second, It looks like what you need to do is create a web method and call it from JQuery for example the following is a web method that accept string
[WebMethod]
public static string GetData(String input)
{
return DateTime.Now.ToString();
}
and you can call it using the same way with your current code just update the url parameter to include the method name
url: "PageName.aspx/MethodName",
for more details about web methods and their union with JQuery please check this article
Edited The following is complete sample
The web method should look like the following one
[WebMethod]
public static string GetData(string filterValues)
{
return filterValues; //This should be updated to return whatever value you need
}
The client side part of calling the web method should look like the following
$.ajax({
url: "/Default/GetData",
type: "POST",
contentType: "application/json; charset=utf-8", //I have added this as "contentType" parameter represents the type of data inside the request meanwhile the "data" parameter describes the data inside the response
data: "{ filterValues:\"" + filterCheckboxes + "\"}", //Note that I have updated the string here also set the name of the parameter similar to the input of the webmethod
dataType: "json",
success: function (result) {
alert(result.d);//You should access the data using the ".d"
}
});
One last thing, If you are using asp.net permanent routing the above code will not work and you should disable it by updating the file "App_Code/RouteConfig.cs" From
settings.AutoRedirectMode = RedirectMode.Permanent;
To
settings.AutoRedirectMode = RedirectMode.Off;
And remember to clear browser cache after the above update

Ajax to MVC controller. Not passing parameters unless Ajax followed by alert

I have the strangest situation. I have two ajax POST. First I had problems passing the parameters to the controller but at some point I got them trough and with some debugging I figured out that I only get all of the values to the controller if my ajax definition is followed by an alert.
One of them:
$.ajax({
type: 'POST',
url: '/Contact/IntresseAnmälan/',
dataType: 'json',
data: {
Namn: $('#namn').val(),
Mail: $('#mail').val(),
Info: $('#meddelande').val(),
Telefon: $('#nr').val(),
IsEnkel: false,
PassId: function () {
var url = window.location.pathname;
var id = url.substring(url.lastIndexOf('/') + 1);
return id;
},
Participanter: getParticipant(),
ParticipantMail: getParticipantMail()
},
traditional: true,
success: function (result) {
// window.location.href = '#Url.Action("IntresseAnmälan", "Contact")';
}
});
alert("Hur sparas dina uppgifter?");
Here are my Getters for name and mail. The form-elements(input type mail and text) theese are dynamicly added to the form if the user wants clicks a button two inputs are added. Then theese functions returns an array with the inputed values from the form.
function getParticipant() {
var p = [];
for (var i = 1; i <= participantCount; i++) {
var name = '#anNamn' + i;
p[i -1] = $(name).val()
}
return p;
}
function getParticipantMail() {
var p = [];
for (var i = 1; i <= participantCount; i++) {
p[i -1] = $('#anMail' + i).val();
}
return p;
}
And here is my controller. I've removed the body in the controller. It saves to the Db and send a verification mail to the admin.
[HttpPost]
public ActionResult IntresseAnmälan(BokningContainer bokning)
{
//Saves to Db and Send a verification mail to admin
}
If I exclude the alert after the ajax some parameters are passed, I think it's Namn and Mail, but most of them not passed. I'm quite puzzled.
Also, is ajax the only way to pass an object to a controller from jQuery?
Also, is ajax the only way to pass an object to a controller from
jQuery?
No, you can use a regular HTML Form to submit your data, you just have to conform to the expected object in the controller Action (should be decorated with HttpPostAttribute) - There is a Model-Binding process which attempting to bind the Request data to your domain object.
You don't need to pass every field's value using jQuery. Instead you can create a form whose data you want to post like :
<form id="frmTest">
... add input types here
</form>
and you can pass data of form using $('#frmTest').serialize() method to the controller
$.ajax({
type: "POST",
data: $('#frmTest').serialize(),
url: "url",
dataType: "json",
success: function (data) { alert('worked!'); },
error: function (data) {
alert('error');
}
});

Categories

Resources