I'm building a HTML page on button click, it will transfer data from localStorage at HTML page to MVC site's action and process action then save data at MVC site
this is my HTML button 's function:
function OH10() {
var url1 = "#Url.Action('createFuel','FuelExtras')";
debugger;
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
var val = localStorage.getItem(key);
$.ajax({
type: "POST",
url: url1,
data: val,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () {
alert("Data has been added successfully.");
},
error: function () {
alert("Error while inserting data");
}
});
}
};
And MVC site 's action:
[HttpPost]
[System.Web.Services.WebMethod]
public ActionResult createFuel(FuelExtra fuelExtra)
{
db.FuelExtras.Add(fuelExtra);
db.SaveChanges();
string message = "SUCCESS";
return Json(new { Message = message, JsonRequestBehavior.AllowGet });
}
Any Suggestions guys?
And 1 more question is right now in development, I've build 2 sites in same Solution, but when I deploy it to intranet i have to separate it into 2 sites. Is it ok?
I found several mistakes in your example:
1) System.Web.Services.WebMethod only used in webforms, it cannot be used for ActionResult in MVC and should be removed.
2) The AJAX callback placed inside a loop, therefore it will execute multiple times instead of single request.
3) The passed data is the last localStorage value taken from getItem() function as single string, not a key-value pair reflecting model property names and their values.
Hence, by assuming you have this model:
public class FuelExtra
{
public string CaptainEmpNo { get; set; }
public string AirCraft { get; set; }
public string FlightNo { get; set; }
public string DepartureAirport { get; set; }
public string ArrivalAirport { get; set; }
// other properties
}
Then you should send key-value pair object as JSON string because the contentType setting has been set to application/json by JSON.stringify(), as in example below:
function OH10() {
var key = []; // array of keys
var val = []; // array of values
var obj = {}; // combined KVP object
var url1 = "#Url.Action("CreateFuel", "FuelExtras")";
debugger;
for (var i = 0; i < localStorage.length; i++) {
key.push(localStorage.key(i));
val.push(localStorage.getItem(key));
}
for (var n = 0; n < key.length; n++) {
obj[key[n]] = val[n]; // create KVP object from both arrays
}
$.ajax({
type: "POST",
url: url1,
data: JSON.stringify({ fuelExtra: obj }), // convert KVP object to JSON string
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
alert("Data has been added successfully.");
},
error: function (xhr, status, err) {
alert("Error while inserting data");
}
});
};
And the controller action should be like this:
[HttpPost]
public ActionResult CreateFuel(FuelExtra fuelExtra)
{
db.FuelExtras.Add(fuelExtra);
db.SaveChanges();
return Json(new { Message = "SUCCESS" });
}
Since you're sending AJAX request as POST method, then JsonRequestBehavior.AllowGet is unnecessary.
Note:
Make sure all key names inside passed JSON string from AJAX is the same as all property names declared inside FuelExtra class.
Related
in my project I have a form with 2 dropdownlist and by clicking a button
it should search in DB and return list of results. this dropdownlist can also be null.
every time I click the button and sent values to my controller via ajax
it shows this error for all my values:
Object reference not set to an instance of an object.
this is my ajax code:
var ValCourse = $("#ddlCourseName").val();
var ValTeacher = $("#ddlTeachers").val();
var CurrentCourseModel = {
CourseNameID: ValCourse,
CourseTeacherID: ValTeacher,
}
var viewModel = {
"CurrentCourseModel": CurrentCourseModel
}
$.ajax({
type: "POST",
url: UrlFindCourse,
data: JSON.stringify(viewModel),
contentType: "application/json; charset=utf-8",
dataType: "json",
cache: false,
success: function (response) {
alert("Success");
}
error: function (response) {
alert("Error");
}
});
and this is my ActionResut:
public ActionResult Courses(CourseModelView viewModel)
{
try
{
CourseRepository repository = new CourseRepository();
CourseModelView model = new CourseModelView();
model.CurrentCourseModel.CourseNameID = viewModel.CurrentCourseModel.CourseNameID;
model.CurrentCourseModel.CourseTeacherID = viewModel.CurrentCourseModel.CourseTeacherID;
model.CurrentCourseModels = repository.FindCourse(model.CurrentCourseModel);
return View(model);
}
catch (Exception Err)
{
LogRepository.Logs.WriteDebug(Err, "error");
return View("~/ HttpError / 500.html");
}
}
the ajax receives all the value correctly I tested that.
but action result says all my values are null
please help me
thank you
you better create a special viewmodel for ajax
public class ViewModel
{
public int CourseNameID {get; set;}
public int CourseTeacherID {get; set;}
}
try this ajax
$.ajax({
type: "POST",
url: UrlFindCourse,
data: { viewModel:viewModel},
success: function (response) {
alert("Success");
}
error: function (response) {
alert("Error");
}
});
and fix the action too
public ActionResult Courses(ViewModel viewModel)
{
CourseModelView model = new CourseModelView{ CurrentCourseModel=new CurrentCourseModel()};
model.CurrentCourseModel.CourseNameID = viewModel.CourseNameID;
model.CurrentCourseModel.CourseTeacherID = viewModel.CourseTeacherID;
model.CurrentCourseModels = repository.FindCourse(model.CurrentCourseModel);
PS. I had to guess to write this code. Pls post CourseModelView class.
In the Controller I added a method to perform some live data exchange into a div.
public class TextItemsController : Controller
{
//[HttpPost]
public JsonResult SpinText(string Body)
{
SpinningResult spinningResult = new SpinningResult();
spinningResult.Spintext = "This is the result text";
string jsonResult = JsonConvert.SerializeObject(spinningResult);
return Json(jsonResult);
}
}
This works in general and the result is sent back to the calling Ajax method and the div is updated with the result text as intended. So the general communication seems to work. But I never receive the input string from the Ajax call.
function doSpinning() {
//var token = $('input[name="__RequestVerificationToken"]', $('#textForm')).val();
var myData = { Body : "Hello" };
//var dataWithAntiforgeryToken = $.extend(myData, { '__RequestVerificationToken': token });
var requestData = JSON.stringify(myData);
$.ajax({
url: "/TextItems/SpinText",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: requestData,
success: function (data) {
var json = JSON.parse(data);
document.getElementById("PreviewText").innerHTML = json["Spintext"];
},
error: function () {
document.getElementById("PreviewText").innerHTML = "Error";
}
});
}
$("#spinButton").on('click', doSpinning);
data seems to have the correct value "{"Body":"Hello"}" before the post but string Body is always null.
Can you try to prefix your parameter with [FromBody] like this :
public JsonResult SpinText([FromBody] DtoBody Body)
And use a data transfer object so the JsonSerializer will know how to map the sent data
public class DtoBody
{
public string Body {get;set;}
}
You are posting an object with a Body property, and your method expects a string value. These don't match up, obviously, but you don't need to post an object when you only want to pass in a primitive:
$.ajax({
url: "/TextItems/SpinText",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: "Hello",
success: function (data) {
var json = JSON.parse(data);
document.getElementById("PreviewText").innerHTML = json["Spintext"];
},
error: function () {
document.getElementById("PreviewText").innerHTML = "Error";
}
});
Note that this is not your only problem though, as you are doing a double JSON serialization on your Action:
// serialize to JSON
string jsonResult = JsonConvert.SerializeObject(spinningResult);
//serialize the serialized object
return Json(jsonResult);
You never have to explicitly serialize to JSON, that's what the helper does for you.
Just use:
public IActionResult SpinText(string Body)
{
SpinningResult spinningResult = new SpinningResult();
spinningResult.Spintext = "This is the result text";
return Json(spinningResult);
}
And, again, you don't need to double-parse the JSON on the AJAX result:
success: function (data) {
document.getElementById("PreviewText").innerHTML = data.spintext;
},
Thanks a lot, I got it with a mix of your help.
DTO
public class SpinningInput
{
public string Title { get; set; }
public string Body { get; set; }
public string Tags { get; set; }
public string Keyword { get; set; }
}
Controller
public JsonResult SpinText([FromBody]SpinningInput spinningInput)
{
SpinningResult spinningResult = new SpinningResult();
spinningResult = Utility.Spinning.SpinText(spinningInput);
return Json(spinningResult);
}
Javascript
function doSpinning() {
const textBody = document.getElementById("Body").value;
const textTitle = document.getElementById("Title").value;
const textTags = document.getElementById("Tags").value;
const textKeyword = document.getElementById("Keyword").value;
var textData = { Title: textTitle, Body: textBody, Tags: textTags, Keyword: textKeyword };
var requestData = JSON.stringify(textData);
$.ajax({
url: "/TextItems/SpinText",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: requestData,
success: function (data) {
document.getElementById("PreviewText").innerHTML = data.spintext;
document.getElementById("WordCount").innerHTML = data.wordCount;
document.getElementById("KeywordDensity").innerHTML = data.keywordDensity + "%";
},
error: function () {
document.getElementById("PreviewText").innerHTML = "Error";
}
});
}
$("#spinButton").on('click', doSpinning);
Using ajax I want to pass 2 objects: string[] and Options to my controller. The problem is that every time string[] in controller scope is set to null.
Thats js code:
$("#exportCsv").click(function () {
var checkboxes = $('.TableChBox:checkbox:checked');
var allIds = [];
for (var i = 0, n = checkboxes.length; i < n; ++i) {
var el = checkboxes[i];
if (el.id) {
allIds.push(el.id);
}
}
console.log(allIds); // it prints ["RId1604678", "RId1604679"]
var form = $('#SearchForm').serialize();
$.ajax({
url: '#Url.Action("ExportToCsv", "Bank")',
type: 'POST',
data: JSON.stringify({
ids: allIds,
options: form
}),
dataType: 'json',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
async: true,
});
});
And thats c# code:
public void ExportToCsv(string[] ids, Options options)
{
// ids is null here
// options is not null
}
When I use debugger I can see, that options is successfully filled, but ids is null. Why does that happen?
Edit 1
As someone suggested I should Add contentType. So I added:
url: '#Url.Action("ExportToCsv", "Bank")',
type: 'POST',
contentType: "application/json; charset=utf-8",
And still - ids is not null, but options is.
Edit 2
Someone suggested to change two parameters in function to one. So I changed my code to:
part of controller
public class ExportModel
{
[JsonProperty(PropertyName = "one")]
public string One { get; set; }
[JsonProperty(PropertyName = "two")]
public string Two { get; set; }
}
[System.Web.Mvc.HttpPost]
public void ExportToCsv([System.Web.Http.FromBody] ExportModel model)
{
//model.One is null
//model.Two is null
}
part of js code
data: JSON.stringify({
one: "foo",
two: "bar"
}),
And even with that simple example with two strings it is not working.
In your controller method you should declare it as accepting a model like so:
public void ExportToCsv(ExportModel model)
{
}
And then define your model like so:
public class ExportModel
{
[JsonProperty(PropertyName = "ids")]
public string[] Ids {get;set;}
[JsonProperty(PropertyName = "options")]
public Options Options {get;set;}
}
As patilprashant6792 pointed out, your ajax request is missing the content type, so you should replace it with this:
$("#exportCsv").click(function () {
var checkboxes = $('.TableChBox:checkbox:checked');
var allIds = [];
for (var i = 0, n = checkboxes.length; i < n; ++i) {
var el = checkboxes[i];
if (el.id) {
allIds.push(el.id);
}
}
console.log(allIds); // it prints ["RId1604678", "RId1604679"]
var form = $('#SearchForm').serialize();
$.ajax({
url: '#Url.Action("ExportToCsv", "Bank")',
type: 'POST',
data: JSON.stringify({
ids: allIds,
options: form
}),
contentType: 'application/json',
dataType: 'json',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
async: true,
});
});
If you don't declare the content type, it will default to application/x-www-form-urlencoded; charset=UTF-8
You should use list of string instead of array & try.
public List<string> Ids {get;set;}
I'm using the USDA food database to try to make an app that will tell you if you've gotten your daily recommendations of vitamins. I'm getting data just fine, but I'm wondering if it was possible to send that data from Angular to the C# api, so I can add the array of strings and int to a total count model.
How would I route this and what kind of data should I tell the API to expect?
The error I'm getting right now is:
Message: "No HTTP resource was found that matches the request URI 'http://localhost/api/apiFood[object Object]'."
MessageDetail: "No type was found that matches the controller named 'apiFood[object Object]'."
I've tried :
public IHttpActionResult Post([FromUri]ValueVM toEat)
{
return Ok();
}
just to see if it would route, but it didn't work out.
I'm sending the data with an ngclick="add(display)" which goes to this function in the controller:
$scope.add = function (display) {
FoodFactory.add(display).then(function (data) {
});
};
and this function in the factory:
o.add = function (display) {
var defer = $q.defer();
var config = { contentType: 'application/json' };
$http.post('api/apiFood' + display, config).success(function (data) {
defer.resolve(data);
});
return defer.promise;
};
In your model
public class toEat
{
public int id {get;set;}
public string name {get;set;}
}
In your ApiController
public class EatController : ApiController
{
[HttpPost]
public HttpResponseMessage Post(List<toEat> list)
{
return Ok();
}
}
Your request
function Request() {
$.ajax({
type: "POST",
url: url,
contentType: "application/json",
data: (your serialized array),
async: false,
success: function(data) {
console.log(data);
}
});
}
I have a test js function that should post data to webapi by Post method
function test() {
var puffs = [];
var puffObject = {
id: "2735943",
priority: "1"
};
puffs.push(puffObject);
puffs.push(puffObject);
var dto =
{
po: puffs
};
$.ajax({
type: "POST",
url: "../api/PuffPriority/",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(dto),
dataType: "json",
success: function (data, status) {
if (data) {
console.log("Welcome");
} else {
console.log("No data");
}
},
error: function (error) {
console.log("Error");
}
});
}
In the controller class i have
public void Post(PuffPriority[] po){
//Do something here with po, but po is always empty
}
where PuffPriority Model is
public class PuffPriority
{
public string id { get; set; }
public string priority { get; set; }
}
I dont know whats wrong , the values are sent by JS but api Controller don't fetch it :( Please help, i have already wasted a lot of time.
You have a bug in your code.
Simply change
url: "../api/PuffPriority/"
to
url: "../api/Post/"
or change your method name from Post to PuffPriority
Changed
public void Post(PuffPriority[] po){
//Do something here with po, but po is always empty
}
To
[FromBody]List<PuffPriority> po{
//Do something here with po, but po is always empty
}