I am using a method in my controller which imports data from an API. This method I am wanted to be called from two locations. First the view (currently working) and secondly a javascript function.
Start of controller method:
[ActionName("ImportRosters")]
[HttpPost]
public ActionResult PerformImportRosterData(int id, int? actualLength, int? rosterLength)
{
var authenticator = Authenticator(id);
var rosters = authenticator.Api().RosterData().ToDictionary(x => x.Id);
var databaseRosterDatas = SiteDatabase.DeputyRosterData.Where(x => x.SiteID == id)
.ToDictionary(x => x.Id);
Javascript Function:
$("#btnDeputyRunNowUpdate").click(function() {
$("#btnRunDeputyNow").modal("hide");
ActualLength = $("#actualRunLength").val();
RosterLength = $("#rosterRunLength").val();
$.ajax({
type: "POST",
url: "/deputy/PerformImportRosterData",
data: { SiteIDRoster, ActualLength, RosterLength }
});
SiteIDRoster = null;
location.reload();
$("#btnRunDeputyNow").modal("hide");
toast.show("Import Successful", 3000);
});
All values are being set but i am getting a 404 error on the url line
POST https://example.org/deputy/PerformImportRosterData 404 ()
I need a way to be able to call this c# method from both html and JS
This can be done if you will modify the URL in your AJAX. It should look something like
url: '<%= Url.Action("YourActionName", "YourControllerName") %>'
or
url: #Url.Action("YourActionName", "YourControllerName")
one more thing, I don't see if you do anything with the result of the call. your script does not have success part
success: function(data) {//do something with the return}
and would be very helpful to have error handler in your call.
full example on how AJAX should look like:
$.ajax({
url: "target.aspx",
type: "GET",
dataType: "html",
success: function (data, status, jqXHR) {
$("#container").html(data);
alert("Local success callback.");
},
error: function (jqXHR, status, err) {
alert("Local error callback.");
},
complete: function (jqXHR, status) {
alert("Local completion callback.");
}
})
For a good tutorial on AJAX read this document
Change after Comment:
my current code is below:
$("#btnDeputyRunNowUpdate").click(function() {
$("#btnRunDeputyNow").modal("hide");
ActualLength = $("#actualRunLength").val();
RosterLength = $("#rosterRunLength").val();
$.ajax({
type: "POST",
url: '<%= Url.Action("PerformImportRosterData", "DeputyController") %>',
data: { SiteIDRoster, ActualLength, RosterLength },
success: function(data) {
console.log(data);
console.log("TESTHERE");
}
});
}
UPDATE:
Noticed one more thing. Your parameters in the controller and AJAX do not match. Please try to replace your a few lines in your AJAX call with:
url: "/deputy/PerformImportRosterData",
data: { id: yourIDValue, actualLength: youractualLengthValue,
rosterLength :yourrosterLengthValue }
remember to set all variable values in javascript , if they have no values set them = to null.
Can you try copy paste code below
$.ajax({
type: "POST",
url: "/deputy/PerformImportRosterData",
data: { SiteIDRoster:999, ActualLength:1, RosterLength:2 }
});
And let me know if it wall cause any errors.
After attempting to solve for a few days, I created a workaround by creating two methods for importing the data. one for the httpPost and the second for import calling from javascript.
Not a great solution but it works. Thanks for your help Yuri
Related
I am trying to pass ID parameter from a view to a controller on a click delete link available on a selected row.
Simplified View Layout
#using (Html.BeginForm("#", "Schedule", FormMethod.Post, htmlAttributes: new { #class = "floating-labels" }))
{
#Html.AntiForgeryToken()
Delete
}
JavaScript
<script type="text/javascript">
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Schedule", new { id = "id" })',
contentType: "application/json",
data: { id },
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
Controller
namespace Controllers
{
public class ScheduleController
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
//do stuff
}
}
}
But on the click of a delete link I get below error and code does not hit controller action.
I am not able to figure out what mistake I am making...
Here is my locally tested implementation that is working.
ScheduleController class:
public class ScheduleController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Delete(int id)
{
return Ok(id);
}
}
Page that sends the post request:
#Html.AntiForgeryToken()
Delete
<div id="ScheduleList"></div>
<script>
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
var uri = '/Schedule/Delete?id=' + id;
var tokenElement = document.getElementsByName('__RequestVerificationToken')[0];
var data = {
__RequestVerificationToken: tokenElement.value
}
$.ajax({
type: "POST",
url: uri,
data: data,
success: function (result) {
success(result);
}
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
The page does nothing but render the html, and the javascript handles the actual Ajax post. What I believe you were missing is the Validation token in your request.
It is because you are not actullay posting the form pass it correctly and add _token in the ajax data list and value for that token will come from #Html.AntiforgeryToken()
reading the error the request is most probably send correctly and there is an internal server error as mentioned in the 500 respond so please check the code that is inside the controller
Try this, you are accesing a javascript variable on c# code, and you cant do that.
If correct, please mark as answer.
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
var url = '#Url.Action("Delete", "Schedule")?id=' + id;
$.ajax({
type: "POST",
url: url,
contentType: "application/json",
data: { id },
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
I think none of the answers above solve the issue. First of all I would replace your target url:
url: '#Url.Action("Delete", "Schedule", new { id = "id" })',
with
url: '#Url.Action("Delete", "Schedule", new { id = actualIdVariable })',
(replace "id" with the actual id variable from the model you're passing to the view).
Note how your browser response is telling you that the url you're posting to is Schedule/Delete/id. That said, I'm not sure you even need the routeValues in this case (the new { id = ...} parameter). this is a POST action, and action parameters wouldn't come from route unless specified by by attribute routing (i.e. [Route("~/Schedule/Delete/{id}")] attribute on your action).
I think your post action is failing because it is trying to parse the "id" string as an int.
Second, I would change the data property of the ajax call and include the anti forgery token. Just because the anchor element you're binding the click event to, is inside the form with #Html.AntiforgeryToken() doesn't mean the generated token will be posted in the ajax request. You're not actually submitting/posting the form, you're just clicking a button.
it should be something like
data: {
'id': id,
'__RequestVerificationToken': $('[name="__RequestVerificationToken"]').val()
}
try this, it solve the error on routing (different url Action) and the parameter on the controller:
JavaScript
<script type="text/javascript">
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Schedule")',
data: "id=" + id ,
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(string id)
{
//do stuff
}
Nicola.
I've been stuck on this problem for a good bit
I'm trying to add an object to my database through jQuery/AJAX. Apparently, there are no errors but it's not adding anything to my DB.
This is my JS/JQuery code:
var student = new Object();
student.Name = $("#txtNameAdd").val();
student.Age = $("#txtAgeAdd").val();
student.Email = $("#txtEmailAdd").val();
$.ajax({
type: "POST",
url: "Default.aspx/AddStudent",
data: "{'studentJSONString':'" + JSON.stringify(student) + "'}",
success: function (response) {
$("#lblSuccessAdd").text("Success!");
$("#lblSuccessAdd").css("display", "block");
},
error: function (response) {
alert(response.responseJSON);
}
});
My JS code points towards this code I have in my Default.aspx page code:
[WebMethod]
public static void AddStudent(string studentJSONString)
{
JavaScriptSerializer converter = new JavaScriptSerializer();
Student a = converter.Deserialize<Student>(studentJSONString);
WebMethods.AddStudent(a);
}
Which points to this code in my WebMethods.cs class
[WebMethod]
public static void AddStudent(Student student)
{
MasterStudent master = new MasterStudent();
master.AddStudent(student);
}
And finally that goes to my class library and finishes with this method in MasterStudent:
public void AddStudent(Student student)
{
if (string.IsNullOrWhiteSpace(student.Name))
{
throw new Exception("There's no name");
}
if (string.IsNullOrWhiteSpace(student.Email))
{
throw new Exception("There's no email");
}
using (studentEntities model = new studentEntities())
{
model.student.Add(student);
model.SaveChanges();
}
}
I run the code and the Console doesn't log any problems but it also doesn't do anything.
I have run very similar code on a Forms application with no problems so I'm kind of in a pickle right now. Does anyone know why it keeps failing?
Have you tried attaching a debugger to it and verifying that the student object is not null prior to model.SaveChanges() ?
Try debugging and verifying that the student string is being converted to an actual Student object first.
If it is, then try profiling the DB and validate any commands issued.
So I actually did find a solution shortly after posting my question, I changed my JQuery AJAX call to look like this:
$.ajax({
type: "POST",
url: "Default.aspx/AddStudent",
data: "{'studentJSONString':'" + JSON.stringify(student) + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
$("#lblSuccessAdd").text("Success!");
$("#lblSuccessAdd").css("display", "block");
},
error: function (response) {
$("#lblErrorAdd").text(response.responseJSON.Message);
$("#lblErrorAdd").css("display", "block");
}
});
And it actually works now! so either the dataType or contentType were very important for what I was trying to do
Thanks for your answers everybody
var student = new Object();
student.Name = $("#txtNameAdd").val();
student.Age = $("#txtAgeAdd").val();
student.Email = $("#txtEmailAdd").val();
$.ajax({
type: "POST",
url: "Default.aspx/AddStudent",
data: student,
success: function (response) {
$("#lblSuccessAdd").text("Success!");
$("#lblSuccessAdd").css("display", "block");
},
error: function (response) {
alert(response.responseJSON);
}
});
Then you can to point to this WebMethod.
[WebMethod]
public static void AddStudent(Student student)
{
MasterStudent master = new MasterStudent();
master.AddStudent(student);
}
Try this.
I have an AJAX function in my javascript to call my controller method. When I run the AJAX function (on a button click) it doesn't hit my break points in my method. It all runs both the success: and error:. What do I need to change to make it actually send the value from $CSV.text to my controller method?
JAVASCRIPT:
// Convert JSON to CSV & Display CSV
$CSV.text(ConvertToCSV(JSON.stringify(data)));
$.ajax({
url: '#Url.Action("EditFence", "Configuration")',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: { value : $CSV.text() },
success: function(response){
alert(response.responseText);
},
error: function(response){
alert(response.responseText);
}
});
CONTROLLER:
[HttpPost]
public ActionResult EditFence(string value)
{
try
{
WriteNewFenceFile(value);
Response.StatusCode = (int)HttpStatusCode.OK;
var obj = new
{
success = true,
responseText = "Zones have been saved."
};
return Json(obj, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
var obj = new
{
success = false,
responseText = "Zone save encountered a problem."
};
return Json(obj, JsonRequestBehavior.AllowGet);
}
}
RESULT
You should change the data you POST to your controller and the Action you POST to:
data: { value = $CSV.text() }
url: '#Url.Action("EditFence", "Configuration")'
The $CSV is possible a jquery Object related to an html element. You need to read it's text property and pass this as data, instead of the jQuery object.
Doing the above changes you would achieve to make the correct POST. However, there is another issue, regarding your Controller. You Controller does not respond to the AJAX call after doing his work but issues a redirection.
Update
it would be helpful for you to tell me how the ActionResult should
look, in terms of a return that doesn't leave the current view but
rather just passes back that it was successful.
The Action to which you POST should be refactored like below. As you see we use a try/catch, in order to capture any exception. If not any exception is thrown, we assume that everything went ok. Otherwise, something wrong happened. In the happy case we return a response with a successful message, while in the bad case we return a response with a failure message.
[HttpPost]
public ActionResult EditFence(string value)
{
try
{
WriteNewFenceFile(value);
Response.StatusCode = (int)HttpStatusCode.OK;
var obj = new
{
success = true,
responseText= "Zones have been saved."
};
return Json(obj, JsonRequestBehavior.AllowGet));
}
catch(Exception ex)
{
// log the Exception...
var obj = new
{
success = false,
responseText= "Zone save encountered a problem."
};
return Json(obj, JsonRequestBehavior.AllowGet));
}
}
Doing this refactor, you can utilize it in the client as below:
$CSV.text(ConvertToCSV(JSON.stringify(data)));
$.ajax({
url: '#Url.Action("EditFence", "Configuration")',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: { value = JSON.stringify($CSV.text()) },
success: function(response){
alert(response.responseText);
},
error: function(response){
alert(response.responseText);
}
});
If your javascript is actually in a JS file and not a CSHTML file, then this will be emitted as a string literal:
#Url.Action("EditFile", "Configuration")
Html Helpers don't work in JS files... so you'll need to point to an actual url, like '/configuration/editfile'
Also, it looks like you're posting to a method called EditFile, but the name of your method in the controller code snippet is EditFence, so that will obviously be an issue too.
you dont need to add contentType the default application/x-www-form-urlencoded will work because it looks like you have a large csv string. So your code should be like this example
$(document).ready(function() {
// Create Object
var items = [
{ name: "Item 1", color: "Green", size: "X-Large" },
{ name: "Item 2", color: "Green", size: "X-Large" },
{ name: "Item 3", color: "Green", size: "X-Large" }
];
// Convert Object to JSON
var $CSV = $('#csv');
$CSV.text(ConvertToCSV(JSON.stringify(items)));
$.ajax({
url: '#Url.Action("EditFence", "Configuration")',
type: "POST",
dataType: "json",
data: {value:$CSV.text()},
success: function(response) {
alert(response.responseText);
},
error: function(response) {
alert(response.responseText);
}
});
Your problem is on these lines:
success: alert("Zones have been saved."),
error: alert("Zone save encountered a problem.")
This effectively running both functions immediately and sets the return values of these functions to the success and error properties. Try using an anonymous callback function.
success: function() {
alert("Zones have been saved.");
},
error: function() {
alert("Zone save encountered a problem.")
}
I'm fairly new to asp.net MVC but am baffled as to why my request isn't working.
I'm trying to send an ajax request with jquery as per:
jQuery(function ($) {
var total = 0,
share = $('div.share'),
googlePlusUrl = "https://plusone.google.com/_/+1/fastbutton?url=http://bookboon.com" + $(location).attr('pathname');
setTimeout(function() {
$.ajax({
type: 'GET',
data: "smelly",
traditional: true,
url: share.data('proxy'),
success: function(junk) {
//var $junk = junk.match(regex);
console.log(junk);
},
error: function (xhr, errorText) {
console.log('Error ' + xhr.responseType);
},
});
}, 4000);
And set a line in my RouteConfig as:
routes.MapRoute(null, "services/{site}/proxy", new { controller = "Recommendations", action = "Proxy" });
The markup has a data-attribute value as:
<div class="share" data-proxy="#Url.Action("Proxy", "Recommendations")">
And my Proxy action method starts with:
public ActionResult Proxy(string junk)
The problem is that the junk parameter is always null. I can see in the debug output that the route seems to correctly redirect to this method when the page loads (as per jQuery's document ready function), but I cannot seem to send any data.
I tried sending simple data ("smelly") but I don't receive that neither.
Any suggestions appreciated!
The model binder will be looking for a parameter in the request called junk, however you're sending only a plain string. Try this:
$.ajax({
type: 'GET',
data: { junk: "smelly" }, // <- note the object here
traditional: true,
url: share.data('proxy'),
success: function(junk) {
//var $junk = junk.match(regex);
console.log(junk);
},
error: function (xhr, errorText) {
console.log('Error ' + xhr.responseType);
},
});
Sure this had been dealt with many times... but.. just cant see what im doing wrong!
This is a simple JS script that Posts data back to ApiController.
function WebCall(url,parameterObject, callBackFunction) {
this.callbackfunction = callBackFunction;
this.parameterObject = parameterObject;
this.url = url;
self = this;
this.GetData = function () {
//self = this;
$.ajax({
//dataType: "json",
type: "POST",
url: self.url,
data: JSON.stringify(self.parameterObject),
contentType: "application/json;charset=utf-8",
success: function (data) {
self.callbackfunction.call(this, data);
},//self.GotData,
error: function (xhRequest, ErrorText, thrownError)
{
alert("error : " + ErrorText)
},
complete: function () {},
})
}
}
The data being sent (parameterObject) is simply
var postData = {
clientId: id
}
The c# code in the controller is :
public class ClientPostObject
{
public string clientId;
}
public class ClientDetailController : ApiController
{
[HttpPost]
public ClientDetailWidgetData GetClient(ClientPostObject clientObject)
{
return new ClientModel().GetClientDetail(clientObject.clientId);
}
}
In Google chrome developer tools, the XHR is showinf 'form Data' as clientId:A0001 - so that looks ok?
No matter what I try (and I'be been through many suggestions on the web), the post data is not there.
Sure its something simple.... Thanks in advance.
Unless you're planning on using a full-on form to submit to this method at some other point, it doesn't really make sense to ask the model binder to attempt to bind to a complex type when you're just using one property. Change your method signature to:
[HttpPost]
public ClientDetailWidgetData GetClient(int clientId) // or whatever type clientId represents
{
return new ClientModel().GetClientDetail(clientId);
}
I'd also recommend adding Glimpse at some point (http://getglimpse.com/) so that you can see how the model binding and/or routing of your app works.
Try to ditch contentType and don't stringify data:
$.ajax({
type: "POST",
url: self.url,
data: self.parameterObject,
success: function (data) {...},
...
});