Angular get data from MVC JsonResult - javascript

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.');
}
);
}

Related

Function not returning data when called by JavaScript

Whilst debugging, using Unit Tests, the function returns the expected data, however when the same function is called from JavaScript, the function is hit but then doesn't return any data.
This function that I'm calling that's in the dll is hanging, but only when it is called by a function that has been called by a JS request, why would this be?
EDIT:
As in comments, my best guess is that it is something to do with a thread being in use, but I don't know, as the function itself is working, just not when called from a C# function called by AJAX.
AJAX call :
function getOnHoldTickets() {
$.ajax({
type: "GET",
url: "/cloud/getTicketCount/",
dataType: "json",
success: function (data) {
onHoldHandler(data);
},
failure: function () {
alert("getOnHoldTickets failled");
}
});
}
Controller :
// api gets hit from the JS call
[Route("cloud/getTicketCount")]
public List<UberTicket> getTicketCount()
{
var tickets = Dashboard.getTODTickets("On Hold");
return tickets;
}
[TestMethod] // calls the same method as JS
public void supportTicketTesting()
{
var openTickets = Dashboard.getTODTickets("On Hold");
var check = openTickets != null;
}
// method calling the dll
public static List<UberTicket> getTODTickets(string type)
{
var tickets = UberAPI.getTODTickets(type);
return tickets;
}
DLL Method:
// the method within the dll that's hanging when called by a function invoked by JS
public static async Task<RootObjectClass<T>> genericGet<T>(string function, string parameters)
{
try
{
// create credentials to pass to httpClient
var httpClientCredentials = new HttpClientHandler()
{
Credentials = new NetworkCredential(uberAPIUser, uberAPIPass)
};
using (var client = new HttpClient(httpClientCredentials))
{
// unsure if the headers are being passed in correctly - getting good response though
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
var response = await client.GetAsync(ubersmithURL + function + parameters);
var result = await response.Content.ReadAsStringAsync();
// remove nulls from json
result = Regex.Replace(result, ":null,", ":\"\",");
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var success = JsonConvert.DeserializeObject<RootObjectClass<T>>(result);
return success;
}
}
catch(Exception ex)
{
// log error
}
return new RootObjectClass<T>();
}
While this might not be addressing the issue fully, you should not be returning C# Data types as JavaScript won't be able to parse them and will result in an error similar to this in the worst case
System.Collections.Generic.List`1[...]
Like I said in my comment, you should return a JsonResult from your controller to retrieve the data in JS.
[Route("cloud/getTicketCount")]
public JsonResult getTicketCount()
{
var tickets = Dashboard.getTODTickets("On Hold");
return Json(tickets ,JsonRequestBehavior.AllowGet);
}
Understanding JsonRequestBehavior.AllowGet
and your Ajax call
$.ajax({
type: "GET",
url: "/cloud/getTicketCount/",
dataType: "json"
})
.done(function(data){
console.log(data);
})
.fail(function(xhr){
console.log(xhr.responseText);
});
Edit:
I believe this is a deadlock issue you have. Perfect answer elaborating the issue is here.

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

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);
}
});

JSON Undefined Error in ASP.NET MVC

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);
}

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