MVC Controller getting 404 error - ajax

I have an MVC controller that has several Methods on it. One to show the View, 6 that are for jquery ajax methods. The View shows up correctly and here is the simple code
public ActionResult Queues()
{
return View();
}
On that view there are 2 datatable.net grids. That grid gets populated with a ajax call to this
[HttpGet]
public async Task<JsonResult> QueueOne()
{
try
{
....
var results = await GetData(queryString, authUser.AccessToken).ConfigureAwait(false);
var jsonObj = JsonConvert.DeserializeObject<DataTableWrapper<QueueItemForRead>>(results);
return Json(jsonObj, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Logger.Error(ex.Message, ex);
}
return Json("Error occured please try again");
}
which populates the grid correctly.
I have other functions on the page that call another endpoint on the page
public async Task<JsonResult> ItemComplete(Guid QueueId, long version)
{
try
{
...
var results =
await
PutData(queryString, JsonConvert.SerializeObject(itemCompleted), authUser.AccessToken)
.ConfigureAwait(false);
var jsonObj = JsonConvert.DeserializeObject<NewItemCommandResult>(results);
return Json(jsonObj, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Logger.Error(ex.Message, ex);
}
return Json("Error occured please try again");
}
and here is the JS that calls the above endpoint
$.ajax({
url: 'http://localhost:18171/Clients/CurrentActivity/ItemComplete' + "?QueueId=" + data + "&version=" + version,
type: 'PUT',
//contentType: 'application/json',
//dataType: 'json',
success: function (result) {
if (result.Result === 2) {
showSuccessNotification(name +
" has been Delivered to table.",
"Food Delivered");
}
//else {
//}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
//Process error actions
console.log(XMLHttpRequest.status + ' ' +
XMLHttpRequest.statusText);
$(buttonName).hide();
},
beforeSend: function () {
// Code to display spinner
$(buttonName).hide();
$(completedAjax).show();
},
complete: function () {
// Code to hide spinner.
$(completedAjax).hide();
}
});
but everytime this function is run all I get a 404 error.
Sorry it was bad cut and paste job, the URL actually has signle quotes around it. and i get the base Url this way
var QueueUrl = '#Url.Action("QueueOne","CurrentActivity")';
so when it renders the actual url is '/Clients/CurrentActivity/QueueOne'

your url doesn't contain " " Or ' ' so it isn't considered as string it should be like
url: "/Clients/CurrentActivity/ItemComplete?QueueId=" + data + "&version=" + version,
Don't Use Your Local Domain IN the Url This Will Cause Problem In production Version if you forget to change it
you can also use Url Helper To Make valid Url Like
url: "#Url.Action("ItemComplete","CurrentActivity",new{area='Clients'})"+"'QueueId=' + data + "&version=" + version,

Related

Web API Post Type action is not getting called by jquery ajax

This is how my web api action look like.
[System.Web.Http.HttpPost, System.Web.Http.Route("BookAppointment/{email}/{id}")]
public System.Net.Http.HttpResponseMessage BookAppointment(string email, int id = 0)
{
System.Net.Http.HttpResponseMessage retObject = null;
if (id > 0 && email!="")
{
UserAppointmentService _appservice = new UserAppointmentService();
bool success = _appservice.BookAppointment(email,id);
if (!success)
{
var message = string.Format("error occur for updating data", id);
HttpError err = new HttpError(message);
retObject = Request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, err);
retObject.ReasonPhrase = message;
}
else
{
retObject = Request.CreateResponse(System.Net.HttpStatusCode.OK, "SUCCESS");
}
}
else
{
var message = string.Format("doc id and emial can not be zero or blank");
HttpError err = new HttpError(message);
retObject = Request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, err);
retObject.ReasonPhrase = message;
}
return retObject;
}
This is my jquery ajax code which suppose to call web api action but throwing error. the error is
No HTTP resource was found that matches the request URI
'http://localhost:58782/api/Appointments/BookAppointment'.
My jquery ajax code as follows.
$('#tblAppointments').on('click', '#btnbook', function () {
var docid = $(this).closest('tr').find("input[id*='hdndocid']").val();
var email = $(this).closest('tr').find("input[id*='hdnpatientemail']").val();
var baseurl = '#ConfigurationManager.AppSettings["baseAddress"]' + 'api/Appointments/BookAppointment';
// + encodeURIComponent(email) + '/' + docid;
alert(baseurl);
$.ajax({
url: baseurl,
type: 'POST',
dataType: 'json',
contentType: "application/json",
data: JSON.stringify({ email: encodeURIComponent(email), id: docid}),
success: function (data, textStatus, xhr) {
console.log(data);
},
error: function (xhr, textStatus, errorThrown) {
var err = eval("(" + xhr.responseText + ")");
alert('Error ' + err.Message);
console.log(textStatus);
}
}).done(function () {
});
});
I have only default route in web api config.
Please tell me what kind of mistake i have done for which it is not working. thanks
There are more problems with your code so I will try to explain them step by step.
1.Based on the code you have provided, you must have decorated your controller with a route like
[RoutePrefix("api/appointments")]
in order to correctly call the BookAppointment method.
If you decorate your controller with this attribute, then you can simply call
http://localhost/api/appointments/BookAppointment/testemail#domain.com/1
and the method would be 100% called.
2.The following code:
var baseurl = '#ConfigurationManager.AppSettings["baseAddress"]' + 'api/Appointments/BookAppointment';
// + encodeURIComponent(email) + '/' + docid;
translates into something like
http://localhost/api/Appointments/BookAppointment
so the necessary part (email/id) are not given (that's why the error message is given).
3.The javascript code makes a POST with JSON in body but your API is not accepting JSON body.
I recommend that you create a separate class like this:
public class BookAppointmentRequest
{
public string Email { get; set; }
public int ID { get; set; }
}
And after that, you modify the method in order to specify that you are accepting data from body.
[HttpPost, Route("BookAppointment")]
public HttpResponseMessage BookAppointment([FromBody] BookAppointmentRequest request)
After that, you can simple make a POST to api/Appointments/BookAppointment with the JSON from your javascript code.
I recommend you to use IHttpActionResult instead of HttpResponseMessage. See this link.

MVC OutputCache JsonResult returns html

I have the following controller:
[HttpPost]
[OutputCache(Duration=3600, VaryByParam="*", Location=OutputCacheLocation.Server)]
public JsonResult FreeTextQuery(SearchFiltersQuery filters)
{
Trace.TraceInformation("Entering method SearchController.FreeTextQuery");
SearchResults aResults = new SearchResults();
if (ModelState.IsValid)
{
try
{
ClaimsPrincipal user = User as ClaimsPrincipal;
aResults = _objectRepository.GetFullTextResults(filters, user);
}
catch (Exception ex)
{
if (!(#Url == null))
{
return Json(new { redirectUrl = #Url.Action("ShowError", "Error", new { message = ex.Message }), isRedirect = true });
}
}
}
Trace.TraceInformation("Exiting method SearchController.FreeTextQuery");
return Json(aResults);
}
which is called by the following ajax function
function GetResults(aFilters) {
var aEndPointUrl = "/Search/FreeTextQuery";
var jSonString = JSON.stringify(aFilters);
$.ajax({
type: 'POST',
url: aEndPointUrl,
traditional: true,
contentType: 'application/json; charset=utf-8',
data: jSonString,
success: function (data) {
// omitted for brevity
},
error: function (xhr, ajaxOptions, error) {
window.location.href = "/Error/ShowError?message=" + encodeURIComponent("Onbekende fout bij het zoeken.");
}
});
This code works fine without the OutputCache attribute on the controller. With it it always hits the error function of the ajax call and I see that the response is not JSON but HTML content (error is a parser error therefore).
What could be going wrong with the outputcaching and how do I get it working correctly? I've tried many ways of supplying VaryByParams but they all have the same result.
This post revealed the answer. The problem was outputting the trace to the page: page outputcache not working with trace

jquery $.ajax call for MVC actionresult which returns JSON triggers .error block

I have the following $.ajax post call. It would go through the action being called but then it would trigger the "error" block of the function even before the actionresult finishes. Also, it seems to reload the whole page after every pass.
var pnameVal = '<%: this.ModelCodeValueHelper().ModelCode%>';
var eidVal = '<%: ViewBag.EventId %>';
var dataV = $('input[ name = "__RequestVerificationToken"]').val();
var urlVal = '<%: Url.Action("New") %>';
alert('url > ' + urlVal);
alert('pname - ' + pnameVal + ' eid - ' + eidVal + ' dataV = ' + dataV);
$.ajax({
url: urlVal,
//dataType: "JSONP",
//contentType: "application/json; charset=utf-8",
type: "POST",
async: true,
data: { __RequestVerificationToken: dataV, pname: pnameVal, eId: eidVal },
success: function (data) {
alert('successssesss');
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest);
alert(textStatus);
alert(errorThrown);
alert('dammit');
}
})
.done(function (result) {
if (result.Success) {
alert(result.Message);
}
else if (result.Message) {
alert(' alert' + result.Message);
}
alert('done final');
//$('#search-btn').text('SEARCH');
waitOff();
});
This is the action
[HttpPost]
public ActionResult New(string pname, int eid)
{
var response = new ChangeResults { }; // this is a viewmodel class
Mat newMat = new Mat { "some stuff properties" };
Event eve = context.Events.FirstOrDefault(e => e.Id == eid);
List<Mat> mats = new List<Mat>();
try
{
eve.Mats.Add(newMat);
icdb.SaveChanges();
mats = icdb.Mats.Where(m => m.EventId == eid).ToList();
response.Success = true;
response.Message = "YES! Success!";
response.Content = mats; // this is an object type
}
catch (Exception ex)
{
response.Success = false;
response.Message = ex.Message;
response.Content = ex.Message; // this is an object type
}
return Json(response);
}
Btw, on fiddler the raw data would return the following message:
{"Success":true,"Message":"Added new Mat.","Content":[]}
And then it would reload the whole page again. I want to do an ajax call to just show added mats without having to load the whole thing. But it's not happening atm.
Thoughts?
You probably need to add e.preventDefault() in your handler, at the beginning (I am guessing that this ajax call is made on click, which is handled somewhere, that is the handler I am talking about).

Posting Image Data From Ajax to WebAPI

I am trying to pass a image dat to a web API method using example code I found on here http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2 and I am finding that MultipartFormDataStreamProvider.FileData is always empty. Why might this be? Also, is this the right approach to be taking? Are there options? I am trying to pass only a single image.
The Call
var t = new FormData();
t.append('file-', file.id);
t.append('filename', file.name);
t.append('Size', file.size);
$.ajax({
url: sf.getServiceRoot('mySite') + "upload/PostFormData",
type: "POST",
data: t,
contentType: false,
processData: false,
beforeSend: sf.setModuleHeaders
}).done(function (response, status) {
alert(response);
}).fail(function (xhr, result, status) {
alert("error: " + result);
});
});
public async Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
I could get fileData properly when posted via form,
as in sample goes # WebAPI upload error. Expected end of MIME multipart stream. MIME multipart message is not complete
Good Luck,

Passing jquery object to MVC action

I am trying to use .ajax() to post a People object to a MVC2 action that expects a ViewModel as parameter. The ViewModel has a People property.
The problem is that when the MVC action is activated, the ajax() postback People object is always null. I used Fiddler to diagnose the problem. The property values in the People object are all contained in the header. Here is my client jQuery script. Please note that I used three methods to stuff the property values into People object, but none of them works.
StaffDlg.delegate("#SaveButton", "click",
function (e) {
e.preventDefault();
People["PKey"] = $("#PKey").val();
People["FName"] = $("#FName").val();
People["LName"] = $("#LName").val();
People["MName"] = $("#MName").val();
People["SSN"] = $("#SSN").val();
People["Gender"] = $("#Gender").val();
People["DOB"] = $("#DOB").val();
People["BirthPlace"] = $("#BirthPlace").val();
People["NetworkAccount"] = $("#NetworkAccount").val();
var pkey = $("#PKey").val();
var action;
if (!isNaN(parseFloat(pkey)) && isFinite(pkey)) {
action = "Edit" + "/" + pkey;
}
else {
action = "Create";
}
$.ajax({
url: getRootUrl() + "/Staff/" + action,
//data: { FName: $("#FName").val(), LName: $("#LName").val(), MName: $("#MName").val(),
// SSN: $("#SSN").val(), Gender: $("#Gender").val(), DOB: $("#DOB").val(),
// BirthPlace: $("#BirthPlace").val(), NetworkAccount: $("#NetworkAccount").val()
//},
//data: JSON.stringify(People),
data: $("Form").serialize(),
dataType: "json",
contentType: "application/json; charset=utf-8",
type: "POST",
success: function (result) {
$("#ajaxResponse").addClass("whiteOnGreen").html("Update succeeded");
},
error: function (qXHR, textStatus, errorThrown) {
$("#ajaxResponse").addClass("whiteOnRed").html("Failed to save the record!\r\n" +
textStatus + ": " + errorThrown + "\r\n" +
"data : " + JSON.stringify(People));
}
})
}
);
and here is the MVC action.
public ActionResult Edit(int id, StaffViewModel updatedStaff)
{
People staff = _staffService.GetStaff(id);
if (updatedStaff == null)
return View("NotFound");
if (ModelState.IsValid)
{
TryUpdateModel<People>(staff, "staff");
staff.RecordLastUpdated = DateTime.Now;
staff.UpdatedBy = HttpContext.User.Identity.Name;
_staffService.SaveStaff();
//return RedirectToAction("Index", new { id = thisStaff.PKey });
if (Request.IsAjaxRequest())
return this.Json(staff, JsonRequestBehavior.AllowGet);
else
{
if (string.IsNullOrEmpty(updatedStaff.previousURL))
return Redirect("/Staff/Startwith/" + staff.LName.Substring(1, 1));
else
return Redirect(updatedStaff.previousURL);
}
}
else
{
if (Request.IsAjaxRequest())
{
string errorMessage = "<div class='whiteOnRed error'>"
+ "The following errors occurred:<ul>";
foreach (var key in ModelState.Keys)
{
var error = ModelState[key].Errors.FirstOrDefault();
if (error != null)
{
errorMessage += "<li>"
+ error.ErrorMessage + "</li>";
}
}
errorMessage += "</ul></div>";
return Json(new { Message = errorMessage });
}
else
return View(updatedStaff);
}
}
You state that the form expects a StaffViewModel as a parameter, and a StaffViewModel has a People property... but you are not passing the full StafFViewModel object - instead you are passing a People object from the Ajax call, and hoping that the People property gets populated on the MVC end.
There is a disconnect there and the auto-binder doesn't know how to bridge it.
Try creating a controller method with a (int, People) signature, and see if that works for you.
Otherwise, you might need to create a custom binder.
Try removing dataType and contentType settings from your ajax call:
$.ajax({
url: getRootUrl() + "/Staff/" + action,
data: $("Form").serializeArray(),
type: "POST",
success: function (result) {
$("#ajaxResponse").addClass("whiteOnGreen").html("Update succeeded");
},
error: function (qXHR, textStatus, errorThrown) {
$("#ajaxResponse").addClass("whiteOnRed").html("Failed to save the record!\r\n" +
textStatus + ": " + errorThrown + "\r\n" +
"data : " + JSON.stringify(People));
}
})
I solved the problem with the .ajax() not posting the form values to the MVC Create(People person) action. It was the parameter type that this different than the one used in Edit(StaffViewModel). Now both action accept the same type of parameter, StaffViewMode.

Resources