viewbag data is empty in $.ajax - viewbag

Iam using asp.net mvc4 and facing some problem in accessing viewbag.price.
This is what i am doing:-
[HttpPost]
public ActionResult FillModel(int id)
{
var vehModel = db.Vehicle_Model.Where(vehMod => vehMod.MakeID == id).ToList().Select(vehMod => new SelectListItem() { Text = vehMod.Model, Value = vehMod.pkfModelID.ToString() });
ViewBag.Price = 100;
return Json(vehModel, JsonRequestBehavior.AllowGet);
}
i am calling above using below:-
$.ajax({
url: '#Url.Action("FillModel","Waranty")',
type: 'post',
data: { id: id },
dataType: 'json',
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '#ViewBag.Price';
},
error: function () {
alert('Error');
}
});
But i am not able to access ViewBag.Price.
Anyone know the reason??
thanks

The reason you aren't able to access items from the ViewBag inside your ajax success function is because the view that contains your script has already been rendered by the Razor view engine, effectively setting the variable a to whatever the value of #ViewBag.Price was at the time the page was rendered.
Looking at the process flow might be helpful:
(1) The request comes in for the view that has your script fragment in it.
(2) The controller method that returns your view is called.
(3) The Razor view engine goes through the view and replaces any references to #ViewBag.Price in your view with the actual value of ViewBag.Price. Assuming ViewBag.Price doesn't have a value yet, the success function in your script is now
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '';
}
(4) The rendered html gets sent to the client
(5) Your ajax request gets triggered
(6) On success, a gets set to the empty string.
As you had mentioned in the comments of your question, the solution to this problem is to include a in the Json object returned by your action method, and access it using data.a in your script. The return line would look like
return Json(new {
model = vehModel,
a = Price
});
Keep in mind that if you do this, you'll have to access model data in your ajax success function with data.model.Field. Also, you shouldn't need to specify the JsonRequestBehavior.AllowGet option, since your method only responds to posts and your ajax request is a post.

Related

MVC5 action that can return either View(model) or json

I have a following problem:
I got an EDIT page, it contains some inputs and so on - nothing unusual. On submit button click I have to validate the form on server and do one of the following actions:
return the model if there are errors
return some info saying it's all good
Why? Because I need to display a bootstrap modal window when everything's ok. So what I did is (simplifying):
[HttpPost]
public ActionResult EditData(DataViewModel model)
{
...
if(!ModelState.IsValid)
return View(model);
return Json(new { success = true, message = "all good" }, JsonRequestBehavior.AllowGet);
}
What is the problem? I'm posting the form with javascript and waiting for the answer like that:
{
$(document).on('click', '#submitButton', function () {
$.ajax({
dataType: "json",
url: "/Controller/EditData",
type: "POST",
data: $('#submitForm').serialize()
}).done(function (data) {
console.log(data.success + ' ' + data.message);
if (data.success) {
$('#modalBody').text(data.message);
$('#modal-window-add').modal('show');
}
});
});
}
So as you can see it does display the modal window but it doesn't do anything when a model comes in. In the latter situation completely nothing happens although the response comes.
Is there any other option to solve my problem? Generally I HAVE to display that modal window on successful edit and on modal closing I need to redirect to another page - this is easy. I tried including the model inside the json but it didn't work and it seems like a lot of work to check all the fields manually and then displaying these red errors under inputs that didn't pass validation. I discussed it with my experienced friends but they don't have any MVC based solution. Any idea?
Best regards,
Daniel
User Ajax For to do that work
#{
var ajaxOptions = new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "modal", OnBegin = "onAjaxBegin", OnComplete = "OnAjaxComplete", OnSuccess = "OnAjaxSuccess" };
}
#using (Ajax.BeginForm("Controler", "EditData", ajaxOptions, new { enctype = "multipart/form-data" }))
{
//write html here with model values
}
COntroller Method
[HttpPost]
public ActionResult EditData(DataViewModel model)
{
if(!ModelState.IsValid)
return View(model);
}
Javascript
function OnAjaxSuccess()
{
show hide model popup
}
$.ajax have a dataType option (The type of data that you're expecting back from the server.)
In $.ajax function you added option dataType: "json" that means you expected json back from server so you will get only json not other dataType like xml, html, text, script
In your case you want to return json or html depending on model is valid or not for that you can remove dateType option from $.ajax function, because If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string).

500 Error when using ajax to get json data

I'm trying to use an ajax call to get json data about my model from my controller. I know 500 error could mean lots of things but I would like to eliminate the possibility of simple error by me.
Console gives me error of: 500 Internal Service Error.
Otherwise I can access it in the url just fine but I don't get anything in the console.
Index.cshtml
function getData() {
$.ajax({
url: "#Url.Action("dataTransfer", "Data")",
type: "GET",
dataType: "json",
success: function(data) {
console.log(data);
},
error: function() {
console.log("failed");
}
});
}
setInterval(function() {
getData();
}, 10000);
DataController
public JsonResult dataTransfer()
{
string DataProvider = "Sample";
var model = from d in db.Data
where d.Name == DataProvider
select d;
return Json(model);
}
500 internal error means your server code is failing, running into an exception because of bad code !
From your code, i can see a problem which could be the cause of your error.
When returning Json from a GET action method, you need to pass JsonRequestBehaviour.AllowGet as the second parameter of Json method.
public JsonResult dataTransfer()
{
string DataProvider = "Sample";
var model = from d in db.Data
where d.Name == DataProvider
select d;
return Json(model,JsonRequestBehavior.AllowGet);
}
Usually in an ASP.NET MVC application, the GET method's are supposed to be returning a view and typically the POST method does some processing on the posted form data/ajax data and return a response, which can be JSON. But if you really want to return Json data from your GET action method, You have to explicitly specify that using the above method we did
Ofcourse, Web API's has a different concept (And implementation behind the scene)

Select2 and JSON Data

I am using select2 version 4 and I have a REST service control on an XPage, that reads the fullname column from the names.nsf.
I have the search working, but for some reason, I don't get a list of values back I can select.
The JSON object being returned, looks something like this:
[{"#entryid":"1376-E6D5EBE8ADBEFA7088257DF8006E4BA2","fullname":"Full Name\/OU\/O"},{"#entryid":"1375-FD1CB92A13BFD0E088257DE4006756D7","fullname":"Another Full Name\/OU\/O"}]
The code to initialize the select2 looks like this:
x$( "#{id:comboBox1}" ).select2({
ajax: {
url: "xJSON.xsp/names",
dataType: 'json',
delay: 250,
data: function (params) {
return {
search:'[fullname=]*'+params.term+'*',
// q: params.term, // search term
page: params.page
};
},
results: function (data, page){
},
processResults: function (data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
console.log(data);
return {
results: data
};
},
cache: true
},
//escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1
});
When I look at the browser's console, I can see that the search worked and JSON objects are being returned, however, I don't get a list of values to select from.
For the result return I've tried results: data.fullname and results: data, text:'fullname' but nothing happens.
What am I doing worng?
You need to either switch your JSON response to include id and text for each object, or re-map them in your processResults method. These two properties are required on all selectable objects now in Select2 4.0. Since I'm assuming you either can't change your JSON response, or it wouldn't make sense to, you can easily re-map the data with the following processResults method.
processResults: function (data) {
var data = $.map(data, function (obj) {
obj.id = obj.id || obj["#entityid"];
obj.text = obj.text || obj.fullname;
return obj;
});
return {
results: data
};
});
This will map the #entityid property to the id property and the fullname property to the text property. So selections will be sent to your server containing the #entityid and will be displayed using the fullname.
Also, the results method is no longer needed in Select2 4.0. This was renamed to the current processResults method.
I copied your code exactly as it is, and just changed the fieldname and the search query and worked out just fine.
This is my JSON looks like
[{"#entryid":"1482-AD112B834158AD0D80257E4B004EC42E","#unid":"AD112B834158AD0D80257E4B004EC42E","id":"Victor Hunter","text":"Odhran Patton"},{"#entryid":"1496-291F2480D806A91E80257E4B004EC3D2","#unid":"291F2480D806A91E80257E4B004EC3D2","id":"Wesley O'Meara","text":"Wesley O'Meara"},{"#entryid":"1421-CC19D06880F5DC2980257E4B004EC537","#unid":"CC19D06880F5DC2980257E4B004EC537","id":"Stephen Woods","text":"Emma Doherty"}]
What I know is that select2 expects an id, and a text parameters from the JSON.

Service retrieves data from datastore but does not update ui

I have a service which retrieves data from the datastore (Web SQL). Afterwards, it stores the data in a AngularJS array. The problem is that this does not initiate changes to the UI.
Contrary, if after the retrieval of data from datastore, I call a web services using a $get method and append the results to the previous array, all data updates the UI.
Any suggestions? Is it possible that I fill the array before the Angular binds the variable?
Can I somehow delay the execution of the service?
Most of the code has been taken from the following example: http://vojtajina.github.io/WebApp-CodeLab/FinalProject/
In order for the UI to magically update, some changes must happen on properties of the $scope. For example, if retrieving some users from a rest resource, I might do something like this:
app.controller("UserCtrl", function($http) {
$http.get("users").success(function(data) {
$scope.users = data; // update $scope.users IN the callback
}
)
Though there is a better way to retrieve data before a template is loaded (via routes/ng-view):
app.config(function($routeProvider, userFactory) {
$routeProvider
.when("/users", {
templateUrl: "pages/user.html",
controller: "UserCtrl",
resolve: {
// users will be available on UserCtrl (inject it)
users: userFactory.getUsers() // returns a promise which must be resolved before $routeChangeSuccess
}
}
});
app.factory("userFactory", function($http, $q) {
var factory = {};
factory.getUsers = function() {
var delay = $q.defer(); // promise
$http.get("/users").success(function(data){
delay.resolve(data); // return an array of users as resolved object (parsed from JSON)
}).error(function() {
delay.reject("Unable to fetch users");
});
return delay.promise; // route will not succeed unless resolved
return factory;
});
app.controller("UserCtrl", function($http, users) { // resolved users injected
// nothing else needed, just use users it in your template - your good to go!
)
I have implemented both methods and the latter is far desirable for two reasons:
It doesn't load the page until the resource is resolved. This allows you to place a loading icon, etc, by attaching handlers on the $routeChangeStart and $routeChangeSuccess.
Furthermore, it plays better with 'enter' animations in that, all your items don't annoyingly play the enter animation every time the page is loaded (since $scope.users is pre populated as opposed to being updated in a callback once the page has loaded).
Assuming you're assigning the data to the array in the controller, set an $scope.$apply() after to have the UI update.
Ex:
$scope.portfolio = {};
$scope.getPortfolio = function() {
$.ajax({
url: 'http://website.com:1337/portfolio',
type:'GET',
success: function(data, textStatus, jqXHR) {
$scope.portfolio = data;
$scope.$apply();
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
};

How to convert JSON array to JavaScript Array?

I am using KnockoutJS for data binding.
Following code is controller's action method
public JsonResult GetPeople()
{
var people = new List<Person>
{
new Person {Name = "aaaa", Address = "aaaaaaaaa"},
new Person {Name = "bbbb", Address = "bbbbbbbbb"},
new Person {Name = "cccc", Address = "ccccccccc"}
};
return Json(people, JsonRequestBehavior.AllowGet);
}
And bellow is the snippet of client side code
<ul data-bind="foreach: people">
<li>NAME:<span data-bind="text: Name"></span></li>
<li>ADDRESS:<span data-bind="text: Address"></span></li>
</ul>
<script>
function getPeopleFromServer() {
var people= [];
$.ajax({
url: "GetPeople",
cache: false,
type: "GET",
success: function (result) {
console.log("result= " + result);
people = $.parseJSON(result);
console.log("people= " + people);
}
});
return people;
}
function ViewModel() {
var self = this;
// data
self.people = ko.observableArray(getPeopleFromServer());
}
ko.applyBindings(new ViewModel());
</script>
The problem is that people variable in the getPeopleFromServer method is always null while result has proper value from the server.
Am I missing something?
Your $.ajax function is taking longer to complete than it's containing function, and so the containing function never popuplates people by the end of execution
One thing you can do is to add the following to your $.ajax:
$.ajax({
async: false,
url: "GetPeople",
.....
});
async: false will make the containing function 'wait' until ajax is finished. Your people var should be populated by the end of function execution. While this is a quick win, I agree with Tom that you should re-think how your ViewModel is handled.
#tom's comment is correct.
'success' is an inline async function. Basically, 'return people' happens before the 'success' function is called, because the ajax call is non-blocking. You need to redesign your ViewModel to work asynchronously (or turn off async), hopefully others will chime in with code fixes
Here's the fully commented fiddle he prophesied.
http://jsfiddle.net/bczengel/8Wqum/
people should be referred to either in the same view model. Or as self.people. I suggest you put the call to ajax inside the view model and then it will be clear.
So getPeopleFromServer() should be inside the viewmodel.
Out of interest you can also add
timeout: 600000 so that the call doesnt timeout.
Try to use ko.mapping plugin.
function ViewModelWrapper(jsonResult)
{
var self = this;
self.model = ko.mapping.fromJS(jsonResult);
}
http://knockoutjs.com/documentation/plugins-mapping.html