Exception management in ASP.NET MVC using jquery - javascript

I have 2 question, in the first one, I get a list, I'd like if excetpion in C# code (controller) has the possibility to a View (an error view) and display it a specific div. How can I get the view in the .error. ?
HTML
<div>List</div>
jQuery
$(".MnuCustomerList").click(function () {
var jqxhr = $.post("/Customer/List", function (data) {
$('#rightcolumn').html(data);
})
.success(function () { alert("success"); })
.error(function () { alert("error"); })
.complete(function () { alert("complete"); });
})
;
Controller:
public PartialViewResult List()
{
throw new Exception("myexception");
return PartialView("List");
}
Second question :
I have a form
#model MyModel
#using (Html.BeginForm("Save", "Customer", FormMethod.Post))
{
<table style="width:100%;">
<tr>
<td>Code</td>
<td>#Html.TextBoxFor(m => m.Customer.Code, new { id = "tbCode" })</td>
</tr>
<tr>
<td>LastName</td>
<td>#Html.TextBoxFor(m => m.Customer.LastName, new { id = "tb", maxlength = 50, style = "width:40%;" })</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="A submit button"/></td>
</tr>
</table>
}
In the Controller, I check if the code already exist, if yes CustomerException("Code exist").
My questions, is it possible to post this form using jQuery BUT still using this format that's mean with the model and NOT get one value by one value like the sample below
$.ajax({
type: "POST",
url: "/Customer/Save",
data: {
id: $('#Id').val(),
firstName: $('#FirstName').val(),
lastName: $('#LastName').val(),
isEnable: $('#IsEnable').attr('checked')
},
success: function (html) {
$("#ContentDataSection").html(html);
},
error: function (XMLHttpRequest, textStatus, errorThrown) { }
});
Thanks,

The error callback is only going to fire if there is an error in making the ajax request. If an error occurs server side, you'll need to pass data back (in Json format would be a good choice) to the client indicating there was a failure server side and handle it in the success callback.
Edit to add code showing how to set response code to 500 so it can be handled in the error call back per Ryan's comment:
Controller action:
public ActionResult FiveHundred()
{
Response.StatusCode = 500;
return Json(new {Error = "Uh oh!"});
}
Javascript:
$.ajax({
url: "/home/fivehundred",
type: "POST",
success: function(data) {
// handle normally
},
error: function(data) {
alert("error " + data.Error);
}
});

Related

Why is the MVC controller action method tagged as HttpPost not getting invoked from external javascript file?

Here is the relevant View cshtml code
<tbody>
#foreach (var task in Model.TasksSummaryList)
{
<tr>
<th onclick="OnPatientSelected('#task.PatientID')">#task.PatientName</th>
<th>#task.Status</th>
<th>#task.TaskCount</th>
<th>#task.MostRecentTask</th>
</tr>
}
</tbody>
Here is the external javascript file containing OnPatientSelected
function OnPatientSelected(selectedPatientID) {
$.ajax({
type: "POST",
url: "TasksSummary/TaksSummaryDetailsView",
data: { selectedPatientID: selectedPatientID },
error: function () {
alert("fail");
},
success: function(){
alert("success");
}
});
}
This always shows success but never calls the Controller ActionMethod I want
[AllowAnonymous]
[HttpPost]
public ActionResult TasksSummaryDetailsView(/*data from view*/string selectedPatientID)
{
int i = 09;
//Received PatientID from View (Client)
//Browse to the appropriate view
return View();
}
The path needs to be relative, try something like the following:
url: "../TasksSummary/TaksSummaryDetailsView",
Or even better:
url: '#Url.Action("TasksSummary", "TasksSummaryDetailsView")',
So replaced the url line in ajax call with the following and it works
url: 'TasksSummaryDetailsView'

How to use jQuery Autocomplete

I have looked at many, many examples and cannot figure out to get the autocomplete to work. Here is my HTML:
<table>
<tr>
<td>
Item Number:
</td>
<td>
<input id="items" />
</td>
<td>
#Html.DisplayTextFor(x=>x.ItemDescription)
</td>
<td>
#Html.TextBoxFor(x=>x.ItemDescription, new { #id = "txtDescription" })
</td>
</tr>
</table>
And here is my C# code:
public ActionResult GetAllItemNumbers(string data)
{
List<string> result = ItemLookup.GetAllItemNumbers(data);
var result1 = result.Where(item => item.Contains(data)).ToList();
return Json(result1);
}
And here is the JS code:
$("#items").autocomplete({
source: function (request, response) {
$.ajax({
type: 'POST',
dataType: "json",
data: {data: request.term },
url: '#Url.Action("GetAllItemNumbers")',
success: function (data) {
response = $.map(data, function (item) {
return {
value: item
};
});
}
});
},
minLength: 4
});
The correct items are being selected and returned to the success function. But there is no drop down being displayed. How do you show the drop down of values that match the input?
According to the Autocomplete demos, response is a callback function to which you should be passing your data. I think you should change this line:
response = $.map(...);
to
response($.map(...));
The response method is what is responsible for building and showing the drop down. It takes the data returned from the controller. In your original code, you are overriding it, so effectively processing stops at that point, and you don't see the drop down being rendered.
Here is an excerpt from the above link for loading items from a remote data source (comments mine):
$( "#city" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "http://gd.geobytes.com/AutoCompleteCity",
dataType: "jsonp",
data: {
q: request.term
},
success: function( data ) {
response( data ); // pass data INTO response, don't assign it
}
});
},
minLength: 3,
// other methods omitted
});

Ajax loading Mvc Content Error

I know, there are several questions with near the same problem. But i cant figure it out, where my mistake is.
So at first my situation:
I'll load my content with ajax and push it to the site.
$.ajax({
url: _this.url,
contentType: "application/html; charset=utf-8",
type: "GET",
dataType: "html",
data: {
stamp: Date.now()
},
success: function (result) {
_this.app = $("<div id='" + _this.frameId + "' />")
.addClass("place-top-left page")
.css({
"height": "100%",
"z-index": 4000
})
.append($(result))
.appendTo(document.body);
if (loadedCallback) {
loadedCallback();
}
},
error: function (xhr, status) {
alert(xhr.responseText);
}
});
My controller:
public ActionResult Edit(int id)
{
var howToContent = Manager.Get(id);
var howToModel = new HowToModel()
{
MediaID = howToContent.Media.ID,
HowToTitle = howToContent.Title,
Name = howToContent.Name,
BusinessIds = howToContent.BusinessIDs.Select(it => it.ToString()).ToArray()
};
return View(howToModel);
}
And my View:
#model Hsetu.Help.Web.Areas.System.Models.HowTo.HowToModel
#{
ViewBag.Title = "Leitfaden bearbeiten";
Layout = "~/Areas/System/Views/Shared/AppSite.cshtml";
}
#section ScriptCSS{
#Scripts.Render("~/uploadScripts")
}
#using (Html.BeginForm())
{
<fieldset>
<label>
#Html.EditorFor(m => m.Name)
</label>
<label>
#Html.EditorFor(m => m.HowToTitle)
</label>
<label>
#Html.EditorFor(m => m.BusinessIds)
</label>
</fieldset>
}
The Error ill get is:
The model item passed into the dictionary is of type Hsetu.Help.Web.Areas.System.Models.HowTo.HowToModel, but this dictionary requires a model item of type System.Web.Mvc.MvcHtmlString
So it will step through the Controller and the View if i debug the code. I'll also get the right model and values!
Only the result on the success function from ajax is a json return with this error message.
This works for same code but without passing this howToModel into the view.
On the other side i found out, if ill use ajaxcall like this it will also work?! Sorry.. but WTF is the diffrence between this ajaxcalls?????
$.ajax({
url: _this.url,
contentType: 'application/html; charset=utf-8',
type: 'GET',
dataType: 'html',
data: {
stamp: Date.now()
}
})
.success(function (result) {
_this.app = $("<div id='" + _this.frameId + "' />")
.addClass("place-top-left page")
.css({
"height": "100%",
"z-index": 4000
})
.append($(result))
.appendTo(document.body);
if (loadedCallback) {
loadedCallback();
}
})
.error(function (xhr, status) {
alert(xhr.responseText);
});
So my question is, how can i get the first ajaxcall working? I need it with this syntax.. so there is no way around. And maybe someone can explain me the difference between the ajax. Doesnt find a really necessary reason!
Thanks
The difference between the ajax calls is that the .error() call on the returned object of the .ajax() call returns a deferred object, which is chainable, and allows multiple handlers to be set, whereas passing in an error: function can only be done once per ajax() call -- I believe that is an older syntax.
(BTW .error() is deprecated, and you should use .fail() instead -- if you were using that approach)
Regarding your MVC (server-side) error: this is often the kind of error message I get when I attempt to pass in an property value that is null into a strongly-typed helper. Check the values of .Name, .HowToTitle, and .BusinessIds for nulls.

.NET MVC JSON Post Call response does not hit complete or success

I am new to .NET MVC so please bear with me.
I wrote a function that gets triggered when there is a blur action on the textarea control:
function extractURLInfo(url) {
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
complete: function (data) {
alert(data);
},
success: function (data) {
alert(data);
},
async: true
})
.done(function (r) {
$("#url-extracts").html(r);
});
}
jQuery(document).ready(function ($) {
$("#input-post-url").blur(function () {
extractURLInfo(this.value);
});
});
This works fine and will hit the controller:
[HttpPost]
public ActionResult Url(string url)
{
UrlCrawler crawler = new UrlCrawler();
if (crawler.IsValidUrl(url))
{
MasterModel model = new MasterModel();
model.NewPostModel = new NewPostModel();
return PartialView("~/Views/Shared/Partials/_ModalURLPartial.cshtml", model);
}
else
{
return Json(new { valid = false, message = "This URL is not valid." }, JsonRequestBehavior.AllowGet);
}
}
I get the intended results if the URL is valid; it will return a partialview to the .done() function and I just display it in code. However, if the URL is not valid i want it to hit either complete, success, or done (I have been playing around to see which it will hit but no luck!) and do something with the returned data. I had it at some point trigger either complete or success but the data was 'undefined'. Can someone help me out on this?
Thanks!
In both cases your controller action is returning 200 status code, so it's gonna hit your success callback:
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
success: function (data) {
if (data.message) {
// Your controller action return a JSON result with an error message
// => display that message to the user
alert(data.message);
} else {
// Your controller action returned a text/html partial view
// => inject this partial to the desired portion of your DOM
$('#url-extracts').html(data);
}
}
});
But of course a much better and semantically correct approach is to set the proper status code when errors occur instead of just returning some 200 status code:
[HttpPost]
public ActionResult Url(string url)
{
UrlCrawler crawler = new UrlCrawler();
if (crawler.IsValidUrl(url))
{
MasterModel model = new MasterModel();
model.NewPostModel = new NewPostModel();
return PartialView("~/Views/Shared/Partials/_ModalURLPartial.cshtml", model);
}
else
{
Response.StatusCode = 400;
Response.TrySkipIisCustomErrors = true;
return Json(new { valid = false, message = "This URL is not valid." }, JsonRequestBehavior.AllowGet);
}
}
and then in your AJAX call you would handle those cases appropriately:
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
success: function (data) {
$('#url-extracts').html(data);
},
error: function(xhr) {
if (xhr.status == 400) {
// The server returned Bad Request status code
// => we could parse the JSON result
var data = JSON.parse(xhr.responseText);
// and display the error message to the user
alert(data.message);
}
}
});
Also don't forget that you have some standard way of returning your error messages you could subscribe to a global .ajaxError() handler in jQuery instead of placing this code in all your AJAX requests.

loading a knockout.js observableArray() from .ajax() call

This puzzles me. It must be something small I'm not seeing. I'm trying to load a very simple observableArray in knockout with an ajax call.
javascript
// we bind the array to the view model property with an empty array.
var data = [];
var viewModel = {
vendors: ko.observableArray(data)
};
ko.applyBindings(viewModel);
$(function () {
// on this click event, we popular the observable array
$('#load').click(function () {
// WORKS. Html is updated appropriately.
viewModel.vendors([{ "Id": "01" },{ "Id": "02" },{ "Id": "03" }]);
// DOES NOT WORK. Fiddler2 shows the same exact json string come back
// as in the example above, and the success function is being called.
$.ajax({
url: '/vendors/10',
dataType: 'json',
success: function (data) {
viewModel.vendors(data);
}
});
});
});
html
<button id="load">Load</button>
<ul data-bind="template: { foreach: vendors }">
<li><span data-bind="text: Id"></span></li>
</ul>
Question: Why does the successful ajax call, who's data variable value matches byte-for-byte the hard typed value, not trigger the html refresh?
There is no reason this would not work fine. As this demonstrates.
http://jsfiddle.net/madcapnmckay/EYueU/
I would check that the ajax post is actually returning json data and that that json is an array and that it's being parsed correctly.
I had to tweak the ajax call to get the fiddle ajax handlers to work correctly.
Nothing more I can think of.
Hope this helps.
var self=this;
//var self first line in model
$.ajax({
url: ",
dataType: "json",
contentType: 'application/json',
type: "POST",
data: JSON.stringify({ }),
processdata: true,
beforeSend: function () {
$.mobile.loading('show');
},
error: function (xhr, textStatus, errorThrown) {
alert('Sorry!');
},
success: function (data) {
$.mobile.loading('hide');
if (data.result!= '') {
self.vendors(data.result);
} else {
self.vendors({something});
}
}
});
Use self.vendors not this viewModel.vendors
Here is what I done in my MVC .net app with knockout and jquery.
// Scripts/groItems.js
(function () {
var ViewModel = function () {
items = ko.observableArray(),
ItemName = ko.observable(),
Img = ko.observable(),
Qty = ko.observable()
}
$.getJSON('/Items2/AllItems', function (data) {
for (var i = 0; i < data.length; i++) {
self.items.push(data[i]);
}
});
var vm = new ViewModel();
$(function () {
ko.applyBindings(vm);
});
}());
#model IEnumerable<GroModel.Item>
#{
ViewBag.Title = "Index";
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div data-bind="text: items().length"></div>
<table class="container table table-hover">
<thead>
<tr>
<th>Item name</th>
<th>img</th>
<th>qty</th>
</tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: ItemName"></td>
<td data-bind="text: Img"></td>
<td data-bind="text: Qty"></td>
</tr>
</tbody>
</table>
#section Scripts {
<script src="~/Scripts/knockout-3.4.2.js"></script>
<script src="~/Scripts/groItems.js"></script>
}
Following is part of my code at the Items2Controller.cs
private GroContext db = new GroContext();
public JsonResult AllItems()
{
return Json(db.Items.ToList(), JsonRequestBehavior.AllowGet);
}
Hope this will help. Thanks
We can use a simple JavaScript util function as a work-around.
Instead of viewModel.vendors(data);, wrapping with eval (research the dangers of eval first) will work.
eval("viewModel.vendors("+JSON.stringify(data)+");");
This is bug I think, Knockout's sample is working when we use it with wrapper class:
public class ResultWrapper
{
public Title {get;set;}
public List<Result> {get;set;}
}
http://learn.knockoutjs.com/#/?tutorial=webmail
But if we return Results directly there is no way to bind it. (without extra applyBindings!)

Categories

Resources