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);
}
});
Related
I am using a DDL in my index page, I get to the action I want, but nothing happens there although my code is right (I mean the result back is like null). But I don't know how or what to do to get data back from my action although I get a success back (when I try it with some alert notion).
This is my index.cshtml code:
$("#SjukhusNamn").change(function () {
$.ajax(
{
type: "POST",
data: { sjukhus: $(this).val(#Model.SjukhusNamn) },
success: function (sjukhus) {
alert("success");
},
url: "#Url.Action("Index", "Home")"
});
});
In my action, a simple [HttpPost] and then
public ActionResult Index(VardplatsOversiktViewModel model, string sjukhus)
{
if (!string.IsNullOrEmpty(sjukhus))
{
model.SjukhusNamn = sjukhus;
model.ListaVardplatsOversikt = db.tblVardplatsOversikt
.Where(s => s.Sjukhus == model.SjukhusNamn)
.ToList();
return View(model);
}
}
sjukhus is hospital in english.
The easiest way would be to convert your Object to JSON, then write it to the response. I like to use the jackson library for this, but there are others. Once you have the Object as a json String, get a PrintWriter and write it to the response with the correct content type:
PrintWriter out = null;
logger.info("Replying to client = " + jsonStr);
try {
out = response.getWriter();
response.setContentType("text/json;charset=utf-8");
out.print(jsonStr);
} catch (IOException e) {
logger.error("Error sending response to client: " + e);
}
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.
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
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.');
}
);
}
I need a cross domain web api method to return valid jsonp to some javascript from C#. I can't seem to make this magic happen. I've looked around the web and can't find a start to end example that fits my needs and works... Fiddler shows that I'm returning valid json data but when I hit a breakpoint in F12 dev tools or firebug the result is a failure message.
Here is what I've currently got:
C#
/// <summary>
/// POST: /Instance/RefreshItem
/// </summary>
/// <param name="instanceId"></param>
/// <returns>Json</returns>
[HttpPost]
public System.Web.Mvc.JsonResult RefreshItem(int instanceId, Guid customerId)
{
try
{
var clientConnection = Manager.ValidateInstance(customerId, instanceId);
clientConnection.RefreshItem();
var result = new MethodResult()
{
Success = true,
Value = instanceId,
Message = "Item successfully refreshed."
};
return new System.Web.Mvc.JsonResult() { Data = result };
}
catch (Exception ex)
{
Manager.LogException(_logger, ex, customerId, instanceId);
var result = new MethodResult()
{
Success = false,
Value = instanceId,
Message = ex.GetBaseException().Message
};
return new System.Web.Mvc.JsonResult() { Data = result };
}
}
JS
Example.RefreshItem = function ()
{
Example.SDK.JQuery.getSettings(
function (settings, userId, userLocaleId)
{
alert("Attempting to refresh item for instance " + settings.ConnectionId + "\r\nThis may take awhile.");
var url = settings.SystemUrl + "/Api/WebApiServices/ExampleAdmin/RefreshItem?customerId=" + settings.CustomerId + "&instanceId=" + settings.ConnectionId;
$.ajax({
url: url,
dataType: "jsonp",
jsonpCallback: 'RefreshItemCallback',
success: RefreshItemCallback
})
},
Example.SDK.JQuery.defaultErrorCallback
);
}
function RefreshItemCallback(data)
{
alert(data.d.Message);
}
I've also tried $.Post().Always() with the same results.
What am I doing wrong???
I think your problem is that you're instantiating a JsonResult instead of using the Json method.
Presumably the C# method you have is in a controller, so instead of
return new System.Web.Mvc.JsonResult() { Data = result };
do:
return Json(result);
This method probably sets some of the other properties of the JsonResult that, when not set, will not be properly received by the client.
See how Microsoft only shows you how to create a JsonResult via the Json method on MSDN
Note that the same is probably true with methods like View, Content, and File.
Fight all week unable to find an answer until you ask the question somewhere... Within 30 minutes of asking I found this: http://bob.ippoli.to/archives/2005/12/05/remote-json-jsonp/ which was exactly what I needed.
Thanks to all who posted.