Call controller which returns view in javascript - asp.net

I am working in ASP.Net MVC. I have following Javascript code in which i am calling a controller-method which returns a view. I want to send parameters to a controller method which re
function fun(p1,p2)
{
// code here to call controller method which returns view
}
public ActionResult ProblemDetails(p1,p2)
{
// here goes some code.
return View();
}
Please tell me the code which can be used to call controller and send parameters too.

Action Method
public ActionResult SendStream(string a, string b)
{
}
JQuery/JSON
Please note that Get Verb will not support complex Data parameters due to it's Query string length constraint. So use POST Verb instead of GET Verb while sending large data
$.ajax({
url: url,
data: JSON.stringify({ a: "a", b: "b" }), //Two String Parameters
type: 'GET', //For Submit, use POST
contentType: 'application/json, charset=utf-8',
dataType: 'json'
}).done(function (data) {
//Success Callback
}).fail(function (data) {
//Failed Callback
}).always(function(data) {
//Request completed Callback
});

Are you perhaps looking to return a Partial View? You can use jQuery ajax to post to a controller method that returns a Partial View (html). You can then render that HTML on the page.
http://mazharkaunain.blogspot.com/2011/04/aspnet-mvc-render-partial-view-using.html

jQuery.get is the shorthand way to achieve this.
function fun(p1,p2)
{
var url = '/controller/ProblemDetails?p1=' + p1 + '&p2=' + p2;
$.get(url, function (data) {
// data will be your response as html
});
}
I might also suggest to have the action return PartialView() instead of View() since you will not return the layout along with the response. It all depends on your intentions for the returned html.

There are several ways to do it.
For example Ajax:
Quick note first: Make sure that in your MVC routing configuration you have a route configured to reflect the following url below:
function fun(p1,p2)
{
var url = '/ControllerName/ProblemDetails?p1=p1&p2=p2' //url to your action method
$.ajax({
url:url,
type:'post' or 'get', //(depending on how you're doing this. If post you can pass data internally instead of query string ),
dataType:'html', //(for example)
success:function(data){
//data here will contain your View info so you can append it do div for example. You can use JQuery .html() function for that
error: function (xhr) {
//catch error
}
}
})
}
Another way, in case if you want to load your View data to DIV is to use JQUery functions such as .load();
function fun(p1,p2)
{
var url = '/ControllerName/ProblemDetails?p1=p1&p2=p2';
$('#YourDivTagForExample').load(url);
}
$.ajax call can also be abbriviated to $.get, $.post or $.getJSON depending on what kind of a call you want to make to your action method. There is a lot more to it too.
Finally make sure to take a look at this answer. Your question was actually already answered in full:
Correct way to handle Ajax calls in ASP.Net MVC 3

Use JSONResult instead of ActionResult and Manipulate return data in javascript.

Related

How do I fill a Javascript var with Json data from a Controller in Asp.net Core

I have a controller that returns a JsonResult
[HttpGet]
public JsonResult ShopMarkers()
{
var shops = repository.Shops;
return Json(shops);
}
In my view I'd like to fill a var with the data from that method. In an older MVC project I remember I'd write an ajax call to fill the var. Something like this:
var markers;
$.ajax({
type: 'POST',
url: '/Map/ShopMarkers',
dataType: 'json',
contentType: dataType,
data: data,
success: function (result) {
markers = result;
}
});
Or I could return a string to a view and Json.Parse it there inside a script tag.
Neither of these seem right. Is there a better way to fill my var in .Net Core?
Your client code is currently making the ajax call with POST type request. But your action method is decorated with HttpGet. So you should be getting a 404 error (If you inspect your browser dev tools, you should be able to see the status of the network (ajax) call)
[HttpPost]
public JsonResult ShopMarkers()
{
var shops = repository.Shops;
return Json(shops);
}
This should work assuming your code inside ShopMarkers method is not crashing ! (throwing any exceptions or so)
In your client side code you are trying to send an object. If you are sending a complex object, you should specify the contentType as "application/json" and send the data using JSON.stringify method.
var dataType = "application/json";
var data = { userId: 12, Password: 'ss' };
$.ajax({
type: 'POST',
url: '/Home/ShopMarkers',
dataType: 'json', // not really needed in your case
contentType: dataType,
data: JSON.stringify(data),
success: function (result) {
var markers = result;
console.log(result);
//Use result only here. Not outside
}
});
Since the ajax call is sending data in the request body, you should decorate the method parameter with [FromBody] attribute so that model binder will be able to map the posted data (from the request body) to your parameter.
[HttpPost]
public JsonResult ShopMarkers([FromBody] YourUserViewModel model)
{
//to do : Return some JSON
}

AJAX promise without Ember Data

I have decided to not use ember-data as it's not production ready and still changing. My app only needs to make a few ajax requests anyway so it shouldn't make too big of a difference. I am having trouble understanding how to handle an ajax promise response.
When my user loads the app they already have an authenticated session. I am trying to ping the server for that users info and display it in my template. It seems my template is rendered before my ajax request returns results and then does not update with the promise.
// route
App.ApplicationRoute = Ember.Route.extend({
setupController: function(){
this.set("currentUser", App.User.getCurrentUser());
}
});
// model
App.User = Ember.Object.extend({
email_address: '',
name_first: '',
name_last: '',
name_full: function() {
return this.get('name_first') + ' ' + this.get('name_last');
}.property('name_first', 'name_last')
});
App.User.reopenClass({
getCurrentUser: function() {
return $.ajax({
url: "/api/get_current_user",
type: "POST",
data: JSON.stringify({})
}).then(function(response) {
return response;
});
}
});
In my template:
<h1> Hey, {{App.currentUser.name_first}}</h1>
How would I update the template when I receive a response or delay rendering until I have a response?
Actually the answer is quite easy: You do not need to use a promise. Instead just return an empty object. Your code could look like this:
App.User.reopenClass({
getCurrentUser: function() {
var user = App.User.create({}); //create an empty object
$.ajax({
url: "/api/get_current_user",
type: "POST",
data: JSON.stringify({})
}).then(function(response) {
user.setProperties(response); //fill the object with your JSON response
});
return user;
}
});
What is happening here?
You create an empty object.
You make an asynchronous call to your API...
... and in your success callback you fill your empty object.
You return your user object.
Note: What is really happening? The flow mentioned above is not the sequence in which those actions are happening. In reality the points 1,2 and 4 are performed first. Then some time later, when the response returns from your server, 3 is executed. So the real flow of actions is: 1 -> 2 -> 4 -> 3.
So the general rule is to always return an object that enables Ember to do its logic. No values will be displayed first in your case and once your object is filled Ember will start do its magic and auto update your templates. No hard work needs to be done on your side!
Going beyond the initial question: How would one do this with an array?
Following this general rule, you would return an empty array. Here a little example, which assumes, that you might like to get all users from your backend:
App.User.reopenClass({
getAllUsers: function() {
var users = []; //create an empty array
$.ajax({
url: "/api/get_users",
}).then(function(response) {
response.forEach(function(user){
var model = App.User.create(user);
users.addObject(model); //fill your array step by step
});
});
return users;
}
});
I'd use Ember.Deferred instead of returning an empty array as mentioned before.
App.User.reopenClass({
getAllUsers: function() {
var dfd = Ember.Deferred.create();
var users = [];
$.ajax({
url: "/api/get_users",
}).then(function(response) {
response.forEach(function(user){
var model = App.User.create(user);
users.addObject(model);
});
dfd.resolve(users);
});
return dfd;
}
});
In your model hook all you have to do is this
model: function(){
return App.User.getAllUsers();
}
Ember is smart enought and knows how to handle the promise you return, once it's resolved the model will be correctly set, you can also return a jQuery promise but it will give you some weird behavior.
You can as well set the current user as the model for your ApplicationRoute like so:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return App.User.getCurrentUser();
}
});
Since getCurrentUser() returns a promise, the transition will suspend until the promise either fulfills or rejects.
This is handy because by the time transition is finished your model is initialized and you will see it rendered in the template.
You can read up more about async routing in Ember guides.

Issue binding JSONP data with Knockout.js

I am working on a web project that involves a cross-domain call, and I decided to use Knockout.js and ASP.NET Web Api. I used the Single Page Application template in VS 2012, and implemented the Knockout class as it is. The page works great when I make JSON call from the same domain, but when I try using JSONP from the remote server the knockout does not seem to bind the data. I can see the JSON data received from the remote while making JSONP call, but knockout cannot bind the data.
Here is my JavaScript ViewModel classes:
window.storyApp.storyListViewModel = (function (ko, datacontext) {
//Data
var self = this;
self.storyLists = ko.observableArray();
self.selectedStory = ko.observable();
self.error = ko.observable();
//Operations
//Load initial state from the server, convert it to Story instances, then populate self
datacontext.getStoryLists(storyLists, error); // load update stories
self.selectStory = function (s) {
selectedStory(s); $("#showStoryItem").click(); window.scrollTo(0, 0);
storyItem = s;
}
//append id to the hash for navigating to anchor tag
self.backToStory = function () {
window.location.hash = storyItem.id;
}
self.loadStories = function () {
datacontext.getStoryLists(storyLists, error); // load update stories
}
return {
storyLists: self.storyLists,
error: self.error,
selectStory: self.selectStory
};
})(ko, storyApp.datacontext);
// Initiate the Knockout bindings
ko.applyBindings(window.storyApp.storyListViewModel);
And my DataContext class as below:
window.storyApp = window.storyApp || {};
window.storyApp.datacontext = (function (ko) {
var datacontext = {
getStoryLists: getStoryLists
};
return datacontext;
function getStoryLists(storyListsObservable, errorObservable) {
return ajaxRequest("get", storyListUrl())
.done(getSucceeded)
.fail(getFailed);
function getSucceeded(data) {
var mappedStoryLists = $.map(data, function (list) { return new createStoryList(list); });
storyListsObservable(mappedStoryLists);
}
function getFailed() {
errorObservable("Error retrieving stories lists.");
}
function createStoryList(data) {
return new datacontext.StoryList(data); // TodoList is injected by model.js
}
}
// Private
function clearErrorMessage(entity) {
entity.ErrorMessage(null);
}
function ajaxRequest(type, url, data) { // Ajax helper
var options = {
dataType: "JSONP",
contentType: "application/json",
cache: false,
type: type,
data: ko.toJSON(data)
};
return $.ajax(url, options);
}
// routes
function storyListUrl(id) {
return "http://secure.regis.edu/insite_webapi/api/story/" + (id || "");
}
})(ko);
This page: http://insite.regis.edu/insite/index.html makes the cross-domain call to secure.regis.edu, and it is not working. However the same page on secure.regis.eduinsite/index.html making JSON call works just fine.
What am I doing wrong? Any help will be greatly appreciated.
Thanks for those provided help.
I manage to solve the issue by adding WebApiContrib.Formatting.Jsonp class to my WebApi project as explained in https://github.com/WebApiContrib/WebApiContrib.Formatting.Jsonp, and making a slight modification to my jQuery Ajax helper class as below:
function ajaxRequest(type, url, data, callbackWrapper) { // Ajax helper
var options = {
dataType: "jsonp",
crossDomain : true,
type: type,
jsonp: "callback",
jsonpCallback: callbackWrapper,
data: ko.toJSON(data)
};
return $.ajax(url, options);
}
Everything worked as a charm.
I suggest the following:
Create a simplified example (without Knockout) that just makes the AJAX call with simple, alert-style success and error callbacks. Affirm that it is throwing an error in the cross-domain case.
Check the following link: parsererror after jQuery.ajax request with jsonp content type. If that doesn't tell you enough, search the Web (and StackOverflow) for information on jQuery JSONP parserrors and callbacks.
If you're still stuck, and you've done #1 and seen what I expect you will see, re-write this post with your simplified example, and remove any references to Knockout (in title, tags). I know Knockout, but I don't know JSONP, and the folks who know JSONP don't seem to be touching this, so I think this question is reaching the wrong audience. Changing the title and tags to emphasize the JSONP/cross-domain aspect may get you the help you need.

How to get jQuery.Ajax to perform a normal POST with a redirect using ASP.NET MVC

I currently have a JSON object on my page which gets built up as users add items to it. This is all done in JavaScript/jQuery.
When the user is done adding items, I want to POST this object to a controller action and have the action return a strongly typed view using this data.
Currently, I have the jQuery.ajax POST sending this JSON object to an Action Method which then binds this object to my strongly typed Model. Problem is, I actually want this jQuery.ajax POST to redirect as if the JSON object were in a FORM and simply being submitted.
I also can't use the jQuery.post() method, which would redirect as required, as I need to be able to set the contentType to "application/json" so my binding works correctly. Unfortunately, the jQuery.post() method doesn't allow you to set this parameter.
I've read that the jQuery.post() method basically uses the jQuery.ajax() method, so I've been battling to get the jQuery.ajax() method to redirect.
I've also read that I can set the default contentType for all jQuery.ajax() methods which would then allow me to use the jQuery.post() method but want to try avoid this if possible.
Thanks
Edit: Updated with Saedeas suggestion:
My JavaScript on the 'Index' View:
<script language="javascript" type="text/javascript">
// Initialize the Shopping Cart object
var m_ShoppingCart = {
UserId: 10,
DeliveryInstructions: "Leave at front desk",
CartItems: []
};
$(document).ready(function () {
$.extend({
postJSON: function (url, data, callback) {
return $.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
success: callback,
dataType: "json",
contentType: "application/json",
processData: false
});
}
});
});
function PostDataWithRedirect() {
var url = '#Url.Action("ConfirmOrder", "Store")';
$.postJSON(url, m_ShoppingCart, function () { });
}
function AddToCart(id, itemName, price, quantity) {
// Add the item to the shopping cart object
m_ShoppingCart.CartItems.push({
"Id": id,
"ItemName": itemName,
"Price": price.toFixed(2), // Issue here if you don't specify the decimal place
"Quantity": quantity
});
// Render the shopping cart object
RenderShoppingCart();
}
function RenderShoppingCart() {
$("#CartItemList").html("");
var totalAmount = 0;
$.each(m_ShoppingCart.CartItems, function (index, cartItem) {
var itemTotal = Number(cartItem.Price) * Number(cartItem.Quantity);
totalAmount += itemTotal;
$("#CartItemList").append("<li>" + cartItem.ItemName + " - $" + itemTotal.toFixed(2) + "</li>");
});
$("#TotalAmount").html("$" + totalAmount.toFixed(2));
}
</script>
And then the Controller Action 'ConfirmOrder'
[HttpPost]
public ActionResult ConfirmOrder(ShoppingCartModel model)
{
return View(model);
}
So when the PostDataWithRedirect() JavaScript method is called it must hit the ConfirmOrder Controller Action and be redirected to the ConfirmOrder View. The Shopping Cart object on my Index view is built up entirely in JavaScript and the user then clicks a 'Proceed to Checkout' button and is redirected etc.
PS: My full working example can be found in an the article [ How to POST a JSON object in MVC ], I just need to update this code so that it can do the post and redirect as explained above
In the success method, do a location.href = "TARGET LOCATION" to cause the page to go to TARGET LOCATION.
$.ajax({
url: myurl,data,
data: myData,
// processData: false, // you may need this option depending on service setup
success: function(){
location.href = "TARGET LOCATION";
},
type: "POST",
contentType: "application/json"
});
Return a view that redirects:
controller
return View("redirectionView");
view
RedirectionView.cshtml
#{
Layout = null;
}
<script type="text/javascript">
alert("Success! Redirecting...");
window.location = "./";
</script>
EDIT
To accommodate data retention use tempdata.
controller
TempData["collectedUserData"] = collectedData;
return View("redirectionView");
RedirectionView.cshtml
#{
Layout = null;
}
<script type="text/javascript">
alert("Success! Redirecting...");
window.location = "./Rebuilder/ActionMethod";
</script>
Controller Rebuilder
public ActionResult ActionMethod()
{
if( TempData.ContainsKey("collectedUserData") )
{
var collectedData = TempData["collectedUserData"];
}
//todo: use else clause to catch data not present
use collectedData to build new view
return View();
}
Maybe I'm not following the question, but why does the classic post, redirect, get pattern not work?
[HttpGet]
public ActionResult WhateverActionName()
{
YourViewModel yvm = new YourViewModel();
//Initalize viewmodel here
Return view(yvm);
}
[HttpPost]
public ActionResult WhateverActionName(YourViewModel yvm)
{
if (ModelState.IsValid) {
RedirectToAction("OtherAction", "OtherController")
}
return View(yvm);
}
Do you mean you want to do a post, have it bind to the viewmodel for validation purposes in one controller, and then have that controller post to another controller that verifies everything? If so, I suggest taking a look at this code to post in c# http://geekswithblogs.net/rakker/archive/2006/04/21/76044.aspx.
Edit: Or you could just place the data in a tempdata object if the other controller action doesn't truly require a post.
Edit 2: Wait, is the question how to do the post with jquery? If so,
$("#YourForm").submit(function () {
$.post('#Url.Action("WhateverActionName", "YourController")';
});
});
Note: may be small syntax errors, but close to that. The #Url.Action is the important part.
Edit 3: This should finally work.
jQuery.extend({
postJSON: function(url, data, callback) {
return jQuery.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
success: callback,
dataType: "json",
contentType: "application/json",
processData: false
});
}
});
Call it in your view as
$.postJSON('#URL.Action("Action", "Controller")', yourJson, callback)
And then redirect inside the controller.

Periodically Refresh a partial view ( ASP.Net MVC)

I need a periodic refresh of .Net's partial view. It is working with Ajax.ActionLink, is there a similar feature for periodic refresh? Can I do it without using jQuery?
Zen, you could do it by a code like this:
function loadPartialView() {
$.ajax({
url: "#Url.Action("ActionName", "ControllerName")",
type: 'GET', // <-- make a async request by GET
dataType: 'html', // <-- to expect an html response
success: function(result) {
$('#YourDiv').html(result);
}
});
}
$(function() {
loadPartialView(); // first time
// re-call the function each 5 seconds
window.setInterval("loadPartialView()", 5000);
});
Remember your Action should return a PartialView.
I hope it helps you!
Maybe this can help you. Which version of MVC are you using? You can set a specified time interval for a helper method. This is the only way I've seen without using js.
Try this.
$(document).ready(function () {
var url = "#(Html.Raw(Url.Action("ActionName", "ControllerName")))";
$("#PartialViewDivId").load(url);
setInterval(function () {
var url = "#(Html.Raw(Url.Action("ActionName", "ControllerName")))";
$("#PartialViewDivId").load(url);
}, 30000); //Refreshes every 30 seconds
$.ajaxSetup({ cache: false }); //Turn off caching
});
It makes an initial call to load the div, and then subsequent calls are on a 30 second interval.
In the controller section you can update the object and pass the object to the partial view.
public class ControllerName: Controller
{
public ActionResult ActionName()
{
.
. // code for update object
.
return PartialView("PartialViewName", updatedObject);
}
}

Resources