Jquery postback not working on mvc 4 client side - asp.net-mvc

I'm trying to simply create a json postback so I can update some controls on the client side. I cant find a good example to show this.
Here's what I got so far which appears to be firing off an alert from the controller but keeps saying 'undefined' object on client side.
What is best practice method of achieving this as I dont know how to debug javascript in the same manner as regular code? :( I'm using vs2012 express, mvc 4, jquery 1.7.1 and jquery mobile 1.1.
My controller Time/Index:
[HttpPost]
public JsonResult Index()
{
var msg = "hello there"; //test message
return Json(msg);
}
My client side:
function populateUserDetails() {
var user = {};
user.UserId = $("#UserId").val(); // potential fields i may use once i get it working
$.post('Time/Index', user, updateFields, 'json');
};
updateFields = function (data) {
alert("hi " + data.msg);
$("#textEntered").val(data.msg);
};
*** UPDATE *********
fixed it by wrapping returned object in controller into a temporary class:
[HttpPost]
public JsonResult Index()
{
var response = new {msg = "hello there"}; //here's what i changed
return Json(response);
}

Replace your last line of code as below.
return Json(response,JsonRequestBehavior.AllowGet);
so it should be like that
[HttpPost]
public JsonResult Index()
{
var response = new {msg = "hello there"};
//here's what i changed
return Json(response,JsonRequestBehavior.AllowGet);
}

Related

Cannot get a response from a Web API call

I have the following in the TreeController controller in a small web API:
[HttpGet("GetDirectories")]
public IActionResult GetDirectories()
{
var baseDir = _config["QuickShare:BaseDir"];
if (string.IsNullOrWhiteSpace(baseDir))
{
throw new InvalidOperationException("'QuickShare:BaseDir' is not configured");
}
var ret = GetDirectories(baseDir); ;
return Json(ret);
}
private List<DirectoryInfo> GetDirectories(string parentDir)
{
var dirInfo = new DirectoryInfo(parentDir);
return dirInfo.GetDirectories("*", SearchOption.TopDirectoryOnly).ToList();
}
When I try and call this action from Postman, I get told
Could not get any response There was an error connecting to
http://localhost:59243/api/Tree/GetDirectories.
Now the default, test, controller that comes with the project template is unchanged:
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] {"value1", "value2"};
}
...
}
And when I have the API running in Visual Studio, I can get a proper response from the Values controller, but not from the TreeController, yet they are almost exactly the same. And, when I call the Tree/GetDirectories` action, a breakpoint in that action method is hit, and I can single step through the very few lines that my method has, and they all execute fine.
The problem only becomes apparent when that last line of the action executes:
return Json(ret);
Then I get shown that Postman Could not get any response despite no exception being raised; while debugging the code, it looks like everything should work fine, and the requests to the Values controller work fine.
Your action method should return either the specific result type (JsonResult when you return Json ) or IActionResult.
Example:
[HttpGet("GetDirectories")]
public JsonResult GetDirectories()
{
var baseDir = _config["QuickShare:BaseDir"];
if (string.IsNullOrWhiteSpace(baseDir))
{
throw new InvalidOperationException("'QuickShare:BaseDir' is not configured");
}
var ret = GetDirectories(baseDir);
return Json(ret);
}
OR
[HttpGet("GetDirectories")]
public IActionResult GetDirectories()
{
var baseDir = _config["QuickShare:BaseDir"];
if (string.IsNullOrWhiteSpace(baseDir))
{
throw new InvalidOperationException("'QuickShare:BaseDir' is not configured");
}
var ret = GetDirectories(baseDir) ;
return Ok(ret);
}
You can get more help from Microsoft Documentation: Formatting Response Data

View not updating after post with ASP.Net MVC

I'm trying to build a very simple website to display some test data being added & updated using asp.net mvc (with razor) but whenever data is posted to my Post method, my data is not being updated. I'm trying to get a unordered list (for now) to be updated the second a post is triggered.
I'm posting my data as JSON using the following code:
string jsonDeviceData = SerializeHelper.Serialize<IDeviceData>(deviceData,
ContentTypeEnum.Json, false);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(localServerUrl);
webRequest.Method = "POST";
webRequest.ContentType = "application/json"; //"application/x-www-form-urlencoded";
byte[] deviceDataBuffer = Encoding.UTF8.GetBytes(jsonDeviceData);
Task<Stream> requestTask = webRequest.GetRequestStreamAsync();
using (Stream requestStream = requestTask.Result)
{
requestStream.Write(deviceDataBuffer, 0, deviceDataBuffer.Length);
}
Task<WebResponse> responseTask = webRequest.GetResponseAsync();
using (StreamReader requestReader = new StreamReader(responseTask.Result
.GetResponseStream()))
{
string webResponse = requestReader.ReadToEnd();
Debug.WriteLine("Web Response: " + webResponse);
}
Below is the code I'm using in the POST method. Don't worry about the logic being so simplistic and probably horrible, but I'm just dabbling with this idea. Data will be stored in SQL Server database and I'll use EF if I decide to go further with this:
[HttpPost()]
public ActionResult Index(DeviceModel model)
{
if (ModelState.IsValid && model != null)
{
var deviceViewModelList = HttpContext.Application["DeviceList"]
as List<DeviceViewModel> ?? new List<DeviceViewModel>();
if (deviceViewModelList.All(m => !string.Equals(m.Name,
model.Name,
StringComparison.InvariantCultureIgnoreCase)))
{
deviceViewModelList.Add(new DeviceViewModel(model));
}
HttpContext.Application["DeviceList"] = deviceViewModelList;
var homePageViewModel = new HomePageViewModel
{
DeviceList = deviceViewModelList
};
return RedirectToAction("Index");
}
else
{
return View();
}
}
My model is passed correctly and everything works ok when the data is posted my page is not updated, even after calling RedirectToAction("Index");
The code below gets called the first time the page is loaded and after calling the RedirectToActio("Index"):
public ActionResult Index()
{
ViewBag.Title = "Test Server";
var deviceViewModelList = HttpContext.Application["DeviceList"]
as List<DeviceViewModel> ?? new List<DeviceViewModel>();
var homePageViewModel = new HomePageViewModel
{
DeviceList = deviceViewModelList
};
return View(homePageViewModel);
}
This is the code I have in my .cshtml page:
<ul>
#if (Model?.DeviceList != null)
{
foreach (var device in Model.DeviceList)
{
<li>#device.Name</li>
}
}
</ul>
If I check Fiddler, the data, in this case, the list is build correctly.
If I press F5 my data is displayed correctly.
I've read so many articles at this stage and I still haven't got a solution, one of them being View not updated after post and while I've tried ModelState.Clear(); and as you can see from my code I'm using #device.Name which is one of the suggestion. I'm not sure about the last one.
Another article I read was ASP NET MVC Post Redirect Get Pattern but again to no avail.
I'm obviously missing something.
Most articles/samples I've been looking at refer to posting via a Form and I know I'm posting, but is that the same as posting via a Form?
Also my page's viewModel is for my page and it contains a list of devices. Is that OK rather than passing the list of device as the viewmodel to the page? The reason I'm doing this is that I will want to access other lists at a later stage.
Has anyone got any suggestions?
Much appreciated.

using angular $http get with asp net web api

I am attempting to use an asp web api to populate an html table using angular. everything works great if I debug in firefox (I'm assuming because my web service is being returned in json) however in ie and chrome it does not load (the web service returns xml in these browsers). In the webapiconfig I attempted to always make the service return json by adding.
Dim appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(Function(t) t.MediaType = "application/xml")
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType)
this appears to work when I navigate to the api in all browsers it is returning json however the $http get is still now working in chrome and ie.
in ie I get the following error
Unhandled exception at line 21, column 406 in http://localhost:53175/Scripts/angular.min.js
0x800a139e - JavaScript runtime error: [$injector:nomod] http://errors.angularjs.org/1.3.13/$injector/nomod?p0=api%2Fproducts
here is my get
angular.module("api/products").constant("dataUrl", "sportstore.json").controller("sportsStoreCtrl", function ($scope, $resource, dataUrl) {
$scope.data = {};
var resultPromise = $resource(dataUrl);
resultPromise.success(function (data) {
$scope.data.products = data;
})
});
any thoughts?
additional info
here is my api controller
<pre>
Imports System.Net
Imports System.Web.Http
Imports apitoform.productRepository
Namespace Controllers
Public Class productController
Inherits ApiController
Private repo As productRepository = productRepository.Current
Public Function GetAllProducts() As IEnumerable(Of product)
Return repo.GetAll()
End Function
End Class
End Namespace
</pre>
and here is the j_son that is being returned ( I am working through the pro Angular book if it looks familiar)
Sorry this is c# code, but it should illustrate the basic idea for returning Json only from web api. It's actual code from one of my projects.
[Route("api/users/getbyemail/")]
public HttpResponseMessage GetByEmail(string email)
{
try
{
var result = _userService.GetByEmail(email);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new ObjectContent(typeof(IEnumerable<UserViewModel>), result ?? new List<UserViewModel>(), new JsonMediaTypeFormatter());
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
catch (Exception ex)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
}
So you are returning HttpResponseMessage with Json content.
I'm also doing similar in a scenario where I just need to return the data from one of the MVC controllers and that is even easier:
public ActionResult Get(string guid)
{
var profileVm = _profileService.Get(guid);
if (profileVm != null)
{
return Json(profileVm, JsonRequestBehavior.AllowGet);
}
return new HttpNotFoundResult();
}
angular.module with 1 parameter returns the module with that name - you need to define your module with a list of dependent modules (or empty array if none) like the following:
angular.module("api/products", [])...
The error referenced gives an error with details on the problem (angular's very good about their error messages): https://docs.angularjs.org/error/$injector/nomod?p0=api%2Fproducts

Calling RazorEngine.Parse() in Controller Action fails with bad HttpContextBase

Perhaps I'm not calling RazorEngine in the correct place.
In my controller action I use the following code to call RazorEngine. But I think this may not be correct as when it calls through to .Execute() and then into MVC's GetActionCache() the HttpContextBase.Items fails with a "method not implemented" exception.
Am I calling RazorEngine in the wrong way? #Html.LabelFor() works fine.
string template = "#Html.EditorFor(model => model.OldPassword)";
string result = string.Empty;
var config = new RazorEngine.Configuration.TemplateServiceConfiguration
{
BaseTemplateType = typeof(System.Web.Mvc.Helpers.HtmlTemplateBase<>)
};
using (var service = new RazorEngine.Templating.TemplateService(config))
{
// Use template service.
RazorEngine.Razor.SetTemplateService(service);
result = RazorEngine.Razor.Parse(template, model);
}
powercat97 over on the github issues page has a workaround for an issue that addresses this.
https://github.com/Antaris/RazorEngine/issues/46
The reason I've had much trouble is that there is no context set. Creating a new ViewContext is not sufficient.
Therefore by calling a view that in turn calls our RazorEngine code via RenderAction() we get the context and the MVC framework has everything it needs when it is called by RazorEngine.
Using the AccountController as an example (HtmlTemplateBase comes from RazorEngine issues with #Html and http://www.haiders.net/post/HtmlTemplateBase.aspx):
public ActionResult Test()
{
var model = new MySite.Models.LocalPasswordModel();
model.OldPassword = "MyOldPwd";
model.NewPassword = "SomeNewPwd";
return PartialView(model);
}
[ChildActionOnly()]
public string TestTemplate(MySite.Models.LocalPasswordModel vm)
{
string result = string.Empty;
string template = "#Html.EditorFor(model => model.OldPassword)";
var config = new RazorEngine.Configuration.TemplateServiceConfiguration
{
BaseTemplateType = typeof(HtmlTemplateBase<>)
};
using (var service = new RazorEngine.Templating.TemplateService(config))
{
// Use template service.
RazorEngine.Razor.SetTemplateService(service);
result = RazorEngine.Razor.Parse(template, vm, "MyTemplateName");
}
return result;
}
and in Test.cshtml:
#model TestRazorEngine.Models.LocalPasswordModel
#{ Html.RenderAction("TestTemplate", new { vm = Model }); }

how to send Json output to view in asp.net mvc

How can i pass the json output from controller action to its view ?
As I tried to send before, My code is :
public ActionResult Index()
{
Guid Id = new Guid("66083eec-7965-4f3b-adcf-218febbbceb3");
List<TasksToOfficer> officersTasks = tasks_to_officer_management.GetTasksToOfficers(Id);
return Json(officersTasks)
}
it is asking for JsonRequestBehavior.AllowJson like parameter. I know it is new in asp.net mvc 2 but as redirect to view there is nothis happens but asking for download the json output file. I want to work with returned data in my jQuery .But something going wrong there. and if I removed the parameter then it is showing error :
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
How to avoid this and get json data at view ?
Here is an example of what you are trying to do. First in your view you call $.getJSON to grab the JSON data from the action:
$.getJSON('/Data/StockQuote', function(data) {
if (data.success) {
ShowStockQuote(data);
}
});
Then your action will look like this:
public JsonResult GetStockQuote()
{
JsonResult result = new JsonResult()
{
Data = new {
lastTradePrice = 50,
lastUpdated = "10/1/2010",
expirationDate = "10/2/2010",
success = true
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return result;
}
Once the JSON data is returned from your action to the $.getJSON you can use data to access all the values off of the JSON object. So data.success will give you the success and so forth.

Resources