JSON Undefined Error in ASP.NET MVC - javascript

I have this JS function:
<script type="text/javascript">
$(function ShowBMI() {
$.getJSON('/BMICalculations/ShowBMI', function (data) {
alert(data.CalculatedBMIResult);
});
});
And in my BMICalculations controller I have this method:
public JsonResult ShowBMI(){
BMICalculation BMI = new BMICalculation();
var data = Json(new
{
CalculatedBMIResult = 6
});
return Json(data, JsonRequestBehavior.AllowGet);
}
I call the JS function using the Onclick event of my submit button. The JS alert says 'undefined'. My Chrome console says that ShowBMI() is undefined but how could this be? Since its defined properly in my controller?

The Json method returns a JsonResult object and not the converted JSON.
So you will end up wrapping your data to a JsonResult and sending the wrapper object to your client instead of your original data.
To fix this you just need to remove your first Json call when creating the data:
public JsonResult ShowBMI()
{
BMICalculation BMI = new BMICalculation();
var data = new
{
CalculatedBMIResult = 6
};
return Json(data, JsonRequestBehavior.AllowGet);
}

Related

Cant get Json from server [duplicate]

I am trying to create controller actions which will return either JSON or partial html depending upon a parameter. What is the best way to get the result returned to an MVC page asynchronously?
In your action method, return Json(object) to return JSON to your page.
public ActionResult SomeActionMethod() {
return Json(new {foo="bar", baz="Blech"});
}
Then just call the action method using Ajax. You could use one of the helper methods from the ViewPage such as
<%= Ajax.ActionLink("SomeActionMethod", new AjaxOptions {OnSuccess="somemethod"}) %>
SomeMethod would be a javascript method that then evaluates the Json object returned.
If you want to return a plain string, you can just use the ContentResult:
public ActionResult SomeActionMethod() {
return Content("hello world!");
}
ContentResult by default returns a text/plain as its contentType.
This is overloadable so you can also do:
return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");
I think you should consider the AcceptTypes of the request. I am using it in my current project to return the correct content type as follows.
Your action on the controller can test it as on the request object
if (Request.AcceptTypes.Contains("text/html")) {
return View();
}
else if (Request.AcceptTypes.Contains("application/json"))
{
return Json( new { id=1, value="new" } );
}
else if (Request.AcceptTypes.Contains("application/xml") ||
Request.AcceptTypes.Contains("text/xml"))
{
//
}
You can then implement the aspx of the view to cater for the partial xhtml response case.
Then in jQuery you can fetch it passing the type parameter as json:
$.get(url, null, function(data, textStatus) {
console.log('got %o with status %s', data, textStatus);
}, "json"); // or xml, html, script, json, jsonp or text
Another nice way to deal with JSON data is using the JQuery getJSON function. You can call the
public ActionResult SomeActionMethod(int id)
{
return Json(new {foo="bar", baz="Blech"});
}
Method from the jquery getJSON method by simply...
$.getJSON("../SomeActionMethod", { id: someId },
function(data) {
alert(data.foo);
alert(data.baz);
}
);
I found a couple of issues implementing MVC ajax GET calls with JQuery that caused me headaches so sharing solutions here.
Make sure to include the data type "json" in the ajax call. This will automatically parse the returned JSON object for you (given the server returns valid json).
Include the JsonRequestBehavior.AllowGet; without this MVC was returning a HTTP 500 error (with dataType: json specified on the client).
Add cache: false to the $.ajax call, otherwise you will ultimately get HTTP 304 responses (instead of HTTP 200 responses) and the server will not process your request.
Finally, the json is case sensitive, so the casing of the elements needs to match on the server side and client side.
Sample JQuery:
$.ajax({
type: 'get',
dataType: 'json',
cache: false,
url: '/MyController/MyMethod',
data: { keyid: 1, newval: 10 },
success: function (response, textStatus, jqXHR) {
alert(parseInt(response.oldval) + ' changed to ' + newval);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error - ' + errorThrown);
}
});
Sample MVC code:
[HttpGet]
public ActionResult MyMethod(int keyid, int newval)
{
var oldval = 0;
using (var db = new MyContext())
{
var dbRecord = db.MyTable.Where(t => t.keyid == keyid).FirstOrDefault();
if (dbRecord != null)
{
oldval = dbRecord.TheValue;
dbRecord.TheValue = newval;
db.SaveChanges();
}
}
return Json(new { success = true, oldval = oldval},
JsonRequestBehavior.AllowGet);
}
To answer the other half of the question, you can call:
return PartialView("viewname");
when you want to return partial HTML. You'll just have to find some way to decide whether the request wants JSON or HTML, perhaps based on a URL part/parameter.
Alternative solution with incoding framework
Action return json
Controller
[HttpGet]
public ActionResult SomeActionMethod()
{
return IncJson(new SomeVm(){Id = 1,Name ="Inc"});
}
Razor page
#using (var template = Html.Incoding().ScriptTemplate<SomeVm>("tmplId"))
{
using (var each = template.ForEach())
{
<span> Id: #each.For(r=>r.Id) Name: #each.For(r=>r.Name)</span>
}
}
#(Html.When(JqueryBind.InitIncoding)
.Do()
.AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
.OnSuccess(dsl => dsl.Self().Core()
.Insert
.WithTemplate(Selector.Jquery.Id("tmplId"))
.Html())
.AsHtmlAttributes()
.ToDiv())
Action return html
Controller
[HttpGet]
public ActionResult SomeActionMethod()
{
return IncView();
}
Razor page
#(Html.When(JqueryBind.InitIncoding)
.Do()
.AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
.OnSuccess(dsl => dsl.Self().Core().Insert.Html())
.AsHtmlAttributes()
.ToDiv())
You may want to take a look at this very helpful article which covers this very nicely!
Just thought it might help people searching for a good solution to this problem.
http://weblogs.asp.net/rashid/archive/2009/04/15/adaptive-rendering-in-asp-net-mvc.aspx
PartialViewResult and JSONReuslt inherit from the base class ActionResult. so if return type is decided dynamically declare method output as ActionResult.
public ActionResult DynamicReturnType(string parameter)
{
if (parameter == "JSON")
return Json("<JSON>", JsonRequestBehavior.AllowGet);
else if (parameter == "PartialView")
return PartialView("<ViewName>");
else
return null;
}
For folks who have upgraded to MVC 3 here is a neat way
Using MVC3 and Json
public ActionResult GetExcelColumn()
{
List<string> lstAppendColumn = new List<string>();
lstAppendColumn.Add("First");
lstAppendColumn.Add("Second");
lstAppendColumn.Add("Third");
return Json(new { lstAppendColumn = lstAppendColumn, Status = "Success" }, JsonRequestBehavior.AllowGet);
}
}
Flexible approach to produce different outputs based on the request
public class AuctionsController : Controller
{
public ActionResult Auction(long id)
{
var db = new DataContext();
var auction = db.Auctions.Find(id);
// Respond to AJAX requests
if (Request.IsAjaxRequest())
return PartialView("Auction", auction);
// Respond to JSON requests
if (Request.IsJsonRequest())
return Json(auction);
// Default to a "normal" view with layout
return View("Auction", auction);
}
}
The Request.IsAjaxRequest() method is quite simple: it merely checks the HTTP headers for the incoming request to see if the value of the X-Requested-With header is XMLHttpRequest, which is automatically appended by most browsers and AJAX frameworks.
Custom extension method to check whether the request is for json or not so that we can call it from anywhere, just like the Request.IsAjaxRequest() extension method:
using System;
using System.Web;
public static class JsonRequestExtensions
{
public static bool IsJsonRequest(this HttpRequestBase request)
{
return string.Equals(request["format"], "json");
}
}
Source : https://www.safaribooksonline.com/library/view/programming-aspnet-mvc/9781449321932/ch06.html#_javascript_rendering

Angular get data from MVC JsonResult

I have the following Action in my MVC Controller:
[HttpPost]
public JsonResult Save(TestModel model)
{
var newId = _myService.CreateItem(model);
return Json(newId);
}
This runs and returns an ID, I see it returning in Fiddler for example as 42. However my angular code it doesn't get the number, but the returned value is shown as data : b, which contains a promise. Is there a way to get the number returned in the data of the success method? My angular code is below:
vm.save = function () {
TestRepository.save(vm.MyData).$promise.then(
function (data) {
// Here data is returned as data : b, not the number
},
function () {
alert('An error occurred while creating this record.');
});
}
my service is
function TestRepository($resource) {
return {
save: function (item) {
return $resource('/mysite/setup/Save').save(item);
}
}
The service is able to call the Action, as I see the code hit my breakpoints, I can see newId also set to 42, but I never see it come back in the angular side.
$resource doesn't support primitive response
As $resource generally used to connect with RESTFUL service, do send data in well formed object, that is how all API does. Sending data from API in primitive type discourage people to use bad pattern. Ideally it should only return JSON object.
[HttpPost]
public JsonResult Save(TestModel model)
{
var newId = _myService.CreateItem(model);
return Json(new {Id = newId});
}
Code
vm.save = function () {
TestRepository.save(vm.MyData).$promise.then(
function (data) {
console.log(data.Id)
},
function () {
alert('An error occurred while creating this record.');
}
);
}

Get return value from Controller to javascript

What I want is, I want to check whether there is a file in the database or not. To do this I have a method in the controller which checks this and returns a boolean for the corresponding case. It looks like this:
public bool fileInDb(int empId)
{
using (SLADbContext db = new SLADbContext())
{
bool file = db.CompetenceUploads.Any(x => x.EmployeeId == empId);
if (file)
{
return true;
}
else
{
return false;
}
}
}
I simply just check if there is any file assigned to the given employee.
Now I would like to call this method from my javascript in the view, and get the return value, so that I can let the user know, if there is a file assigned to the selected employee or not. It may look like this:
$("#get-file").click(function() {
empId: $("#EmployeeSelect").val();
var fileInDb = // Get the return value from the method 'fileInDb'
if(fileInDb) {
// Let the user download the file he/she requested
var url = "#Url.Action("GetUploadedFile", "Competence")";
this.href = url + '?empId=' + encodeURIComponent($("#EmployeeSelect").val());
} else {
alert("There is no file assigned to this employee.");
}
});
So my question now is, how do I get the get the return value from the method in the controller?
I would suggest few changes here:
Change your controller method to have return type ActionResult or JsonResult and I prefer JsonResult would be enough here and retrun Json response from controller and manipulate this method with $.get. You also need to change parameter to string because the parameter will be received as Json string.
public JsonResult fileInDb(string eId) //change signature to string and then convert to int
{
int empId=Convert.ToInt32(eId);
using (SLADbContext db = new SLADbContext())
{
bool file = db.CompetenceUploads.Any(x => x.EmployeeId == empId);
if (file)
{
return Json(new { result = true },JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { result = false},JsonRequestBehavior.AllowGet);
}
}
}
Now your ajax-get call would be as below:
$("#get-file").click(function() {
var eId= $("#EmployeeSelect").val();
$.get('/YourControllerName/fileInDb',{'eId':eId},function(response){
//you just need to get the response so $.get is enough to manipulate
//this will be called once you get the response from controller, typically a callback
if(response.result) //same result variable we are returning from controller.
{
// Let the user download the file he/she requested
var url = "#Url.Action("GetUploadedFile", "Competence")";
this.href = url + '?empId=' + encodeURIComponent($("#EmployeeSelect").val());
} else {
alert("There is no file assigned to this employee.");
}
})
});
You need to set-up a single page script using your ASP fileInDb function and then communicate with that page using AJAX from the browser. If you're unfamiliar with AJAX I'd recommend using the jQuery implementation to get you started.
You can use jquery and ajax to achieve this. Call your method using an ajax call from your client code. Here is an example as a reference :Calling controller method from view
In the backend create a method to call, returning a JsonResult
public JsonResult fileInDb(int empId)
{
// your code - set fileExists to true/false
JsonResult returnObj = new JsonResult
{
Data = new
{
FileExists = fileExists ;
}
};
return Json(returnObj);
}
in your javascript code use $.ajax
$.ajax({
cache: false,
url: '#Url.Action("fileInDb")',
data: { 'empId': someVar },
type: 'POST',
success: function (response) {
if (response.Data.FileExists === true) {
// do something
} else {
// it was false
}
},
error: function (er) {
alert('Error!' + er);
}
});

Passing Model Data to JSON in ASP.NET MVC (returning null)

I have this code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(BMICalculation CalculateBMI)
{
if (ModelState.IsValid)
{
CalculateBMI.Id = User.Identity.GetUserId();
CalculateBMI.Date = System.DateTime.Now;
CalculateBMI.BMICalc = CalculateBMI.CalculateMyBMI(CalculateBMI.Weight, CalculateBMI.Height);
CalculateBMI.BMIMeaning = CalculateBMI.BMIInfo(CalculateBMI.BMICalc);
ShowBMI(CalculateBMI.ToString());
db.BMICalculations.Add(CalculateBMI);
db.SaveChanges();
}
return View();
}
public JsonResult ShowBMI(string BMICalculation){
BMICalculation BMI = new BMICalculation();
var data = new
{
BMICalculation
};
return Json(data, JsonRequestBehavior.AllowGet);
}
I want the BMI calculation to be passed from the Create(BMICalculation CalculateBMI) method to the ShowBMI method so that it can be then passed to my webpage as a Json value.
The javascript function is called by submit button (which also processes the form):
<button type="submit" id="submit" onclick="ShowBMI();"> <span class="glyphicon glyphicon-floppy-save"></span></button>
And my JS is
<script type="text/javascript">
$(function ShowBMI() {
$.getJSON('/BMICalculations/ShowBMI', function (data) {
alert(data.BMICalculation);
});
});
</script>
When I click the submit button an alert appears saying null even though I have values in my webpage textboxes. Is there a way around this in my controller?
Update 1 - So I've changed my Create() code but now I dont understand ' and then change your code so that you do an Ajax POST, with your serialized form'
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Create(BMICalculation CalculateBMI)
{
if (ModelState.IsValid)
{
CalculateBMI.Id = User.Identity.GetUserId();
CalculateBMI.Date = System.DateTime.Now;
CalculateBMI.BMICalc = CalculateBMI.CalculateMyBMI(CalculateBMI.Weight, CalculateBMI.Height);
CalculateBMI.BMIMeaning = CalculateBMI.BMIInfo(CalculateBMI.BMICalc);
db.BMICalculations.Add(CalculateBMI);
db.SaveChanges();
}
var data = new
{
BMICalculation = CalculateBMI.BMICalc,
BMIInfo = CalculateBMI.BMIMeaning
};
return Json(data, JsonRequestBehavior.AllowGet);
}
If I understood you right, when you are clicking the submit button, you are actually performing two requests, unaware of eachother:
One regular form post, that's processed, and returns with the view.
An Ajax GET request, that gets some data from ShowBMI on your controller. This Action requires a string and since you're not passing it any data, it returns null.
Again, if I understood you correctly, the scenario you want to achieve is that when you POST your form, you want a Json payload back with the processed result.
If that is correct, then what you'd probably want to do in have your Create action return the Json , and then change your code so that you do an Ajax POST, with your serialized form.Then in your Ajax success handler process the result you get back, just like you're doing now. I hope my intent is clear, otherwise, please ask for clarification. :)
You have to pass the required parameters to the method in controller...
You should try something like this..
function ShowBMI() {
$.ajax({
url: "#Url.Action("Create", "Your Controller")",
data: {
'CalculateBMI': your Data
},
dataType: 'json',
type: 'POST',
success: function (response) {
try {
alert(response.BMICalculation);
}
catch (error) {
}
},
error: function () {
}
});
}
Use With
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(BMICalculation CalculateBMI)
{
if (ModelState.IsValid)
{
return Json(obj, JsonRequestBehavior.AllowGet);
}
else
{
return View();
}
}
You can get the method using ActionResult and return it with Json Obejct also

calling controller from method from JavaScript

I am developing a web site using MVC 3 razor, in which I have the following situation:
A controller method:
public ActionResult MyControllerMethod(int parameter){
''go to bd a do some staff
IList<My_Custom> datafromDB = MyService.GetData(parameter);
'returns to my string tuped view
return View(datafromDB );
}
A strong typed view in which I use JavaScript:
#model IList<My_Custom>
<script type="text/javascript">
function getData()
{
var parameter = document.getElementById('myParamater').value;
$.get('/MyController/MyControllerMethod/' + parameter, function (data) {
loadData();
}
);
}
function loadData()
{
clearData();
datos = #Html.Raw(Json.Encode(Model));
//do some stuff with datos
}
</script>
The JavaScript call to the controller works fine but my problem is that the string typed view seems like is not taking the new value for the #model, so keeps loading the same information.
Although I have debugged the action controller and it returns different data every time.
So is there any way to refresh the Model value of a string typed view?
I also tried to process the data value of that line
$.get('/MyController/MyControllerMethod/' + parameter, function (data) {
but I wasn't successful doing that.
Your action return view, that's why nothing works. How your code works:
Load data in action, then generate view with json on the page
Send requst to the server and receive html with json (all this data are in memory),
then you access json from first step
How it must work:
Create view
Send request to the server (another method, that returning Json)
Access data
public ActionResult YourJsonAction(int parameter)
{
IList datafromDB = MyService.GetData(parameter);
return Json(datafromDB, JsonRequestBehavior.AllowGet);
}
function getData()
{
var parameter = $('#myParamater').val();
$.get('/MyController/YourJsonAction/' + parameter, function (data) {
//data from YourJsonAction
});
}

Categories