Assign values to ViewData from client using MVC - asp.net-mvc

I inherited an MVC app and am a true novice at it coming from an ASP.NET environment. My problem is I can't manage to move variable data between my partial views and controllers. In ASP.NET this was pretty straight forward, not the case in MVC. So the following code fires when a Tab is selected from the client but I need to capture the selectedTabIndex value from the client and pass it to the controller.
function onTabSelect(e) {
var selectedTabIndex = 0;
selectedTabIndex = $(e.item).index();
alert(selectedTabIndex);
}
I considered using the ViewData object but there doesn't appear to be a way to make perform this task of assignment from within the function. So the following code would seem to be a ridiculous task and it fails anyway. (Remember, I am an extreme novice at this)
function onTabSelect(e) {
var selectedTabIndex = 0;
<% =ViewData["selectedTabIndex"]%> = selectedTabIndex;
}
I also considered using cookies but that doesn't seem to be a practical method either. In ASP.NET I could access the client controls using the .find method but this is a steep learning curve for me.
What are my alternatives?

If different tabs can be selected by the user between Save operations, you might need to consider binding some kind of click function (using jQuery) to set the selectedTabIndex javascript variable. Alternatively, you could set a hidden input's value to the selected tab index.
In either case, if you need the value in your controller (to set ViewData, ViewBag, some model data, etc) when a Save operation is submitted, you could submit the data via $.ajax and return some JSON from your controller
$('#SaveButton').click(function() {
$.ajax({
url: '/Controller/Save',
type: 'POST',
// you might need to serialize additional data you want to save here
// but you could create any JSON object before calling $.ajax
data: {"selectedTabIndex": selectedTabIndex}, // data to POST
dataType: 'json', // this indicates the type of data returned from controller
success: function(data) {
// you didn't really describe how to programatically set a tab,
// so "setToTab" is a guess
$('#tabID').setToTab(data.selectedTabIndex);
}
});
}
And your controller might look something like
public ActionResult Save(int selectedTabIndex)
{
// again, you might need different parameters to complete your Save
return JsonResult(new { selectedTabIndex: selectedTabIndex });
}

Data is sent to a controller via a HTTP POST. Create a hidden input <input type="hidden" name="selectedTabIndex"/> and set the value with javascript prior to POST. The controller can extract this value from the Form parameters, or it can be autopopulated in the Action method if the method contains a parameter matching the input name.
This is a non-ajax alternative to the answer provided by David.

Related

How to do MVC form with very simple lookup?

We have a very simple MVC form with a dropdownlist which gets the user's selected city.
We have a list of cities and we know the average temperature (say) for each city.
Almost as a decoration (it's not a core function) for the form it would be nice to show the temperature for the selected city as the user changes it. Something like this:
This has to happen client side, I guess. Or is it AJAX?
At the moment our form is mostly out-of-the-box MVC4 EF auto built with scaffolding.
We populate the dropdownlist like so:
In the Controller:
ViewData("Cities") = GetCitySelectList()
and in the View:
#Html.DropDownListFor(Function(model) model.City, TryCast(ViewData("Cities"), SelectList))
... so pretty simple stuff.
There are plenty of tutorials for doing cascading dropdowns which are probably overkill for what we're trying to do here. Also if you google "javascript lookup mvc form" or similar a lot of the results tie you to using a framework (knockout? barebone?) which, again, I'm not familiar with and I don't know if I need for such a simple task.
In fact we're so geared to keeping it simple, and our city list is so short, it's almost worth doing it as a giant if then else in javascript (but, I know, yuk).
What's the simplest way to do this?
You can do it as follows:
Make an Ajax call on change on dropdown and then place the result in the corresponding div.
Html for result:
Temperature:<div id="temp"></div>
Ajax call :
$("#dropdownId").change(function () {
$.ajax({
type: "GET",
url: "Home/GetTemperature", // your url
contentType: "application/json; charset=utf-8",
data : {City : " + $(this).val() +"}
dataType: "json",
success: function (result) {
$("#temp").html(result); // place result in div
},
error: function () {
alert("Error.");
}
});
});
Your Action (C#):
[HttpGet]
public JsonResult GetTemperature(string City)
{
int temp = 30; // Get temp from your db..
return Json(temp,JsonRequestBehavior.AllowGet);
}
Your Action (VB):
<HttpGet>
Public Function GetTemperature(City As String) As JsonResult
Dim temp As integer = 30
Return Json(temp, JsonRequestBehavior.AllowGet)
End Function
You should use AJAX call to the server for the temperature. That's probably the "cleanest" way to achieve what you would like to have on your form.
Option 1: Using jQuery and make ajax call to fetch a temprature for the cityId passed and set the html of the temprature div or span container
Option 2: Eager Load on page as Javascript object
You could have eager load the cities and temprature into the JSON object and store it.
Here is the controller action code using JSON.Net for json serialization
public ActionResult myAction()
{
MyViewModel model=new MyViewModel();
List<City> cities=new List<City>();//fill the city id, temp
MyViewModel.CityJSON=JsonConvert.SerializeObject(List<City>);
return View(model)
}
View
#model MyViewModel
// other controls
#Html.HiddenFor(m=>m.CityJSON, new{#id='hdn-city-json'})
JavaScript
var cityList=JSON.parse($('#hdn-city-json')); // returns array of city obj
//do your stuff
If you are trying to avoid unneccesary requests to server, yes, you could eager load the whole collection. You can keep the data in a hidden <ul/> tag that you build on your View. Then, you can use jQuery to fire when the dropdown selection changes. But instead of making an AJAX call, you can lookup the temperature in the list instead and set the content of the target div to the return value of the lookup function.

Can i pass JSON instead of Model from my controller to my Razor view

I have a view that inherit the following:-
#model MvcApplication.Models.Application
But i need to know if it is possible to pass JSON objects to my view in the same way i am passing the model objects?
Since i have the following Controller:-
public ActionResult ListPackages()
{
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
//code goes here ....
return Content(json, "application/json");
}
}
which returns JSON using a API call, and then i am displaying the JSON on the view using JavaScript as follow:
$.ajax({
url: $('#geturl').data('url'),
type: 'GET',
cache: false,
success: function (result) {
$.each(result.data, function (key, val) {
var str = val.packageName;
$('<li/>', { text: str })
.appendTo($('#products'));
});
}
The problem with displaying the JSON using JavaScript is that it will make too difficult for me to work easily with the JSON objects, such as creating links based on the returned JSON or creating table that contain the JSON. So my question is: Is it possible to pass a JSON object instead of a Model object from my controller to my view?
Server- vs client-side confusion
You're talking two things here:
Creating a view: controller passes model to the view on the server side and it doesn't make much sense to do so using JSON, because an in-memory object is being passed to view engine.
Consuming JSON data on the client: what you're talking about here is client-server Ajax communication where you request data from the client and get JSON returned from the server. This has arguably nothing to do with model data being passed to the view
Best solution using JSON
In order to easily consume JSON data (in your case it's an array of packages) on the client to generate resulting populated HTML is to use some sort of templating on the client side. jQuery used to have non-final templating plugin which is now a separate project. I've had great experience with it but there are other plugins as well. Use the one that you feel most comfortable with its syntax.
Where to put those templates?
If you know the structure of your JSON objects passed from the server at the point of creating your view, you can put templates in the view itself and they'll just wait untill being used on the client.
If you don't know the structure of your JSON objects then you'll have to pass templates either along JSON object or as a separate request.
The first approach is the usual one, the second one is rarely used and is much more dynamic.
Best solution not using JSON
If you don't like parsing JSON to HTML results (either manually or using templates), you can always make Ajax requests to your controller action, which would return a prepared HTML as a partial view instead of JSON result. This way, you could easily just put that HTML onto your page without any JSON data manipulation.
What do you gain here? Well suppose you have this functionality in your app:
You have a view that displays a paged list of packages.
When user first accesses the page first page of packages are being returned
Paging to next page is done via Ajax and the list is being replaced by returned data
If you'd create a partial view for your subsequent Ajax request, you can use the same partial view in your main view to display the first page of packages. This will ensure that you only have to change one partial view and display would change on inital page load as well as subsequent package paging.
If you used view + JSON + templating that means that you have to maintain two presentations of package list: the one being used in the view for the first page and the template that displays subsequent paging.
Which one then?
All things being equal it makes the second solution better. But the choice of course depends on your case (of things not being equal) and you should be able to determine which one is best in your scenario.
No, you can't. A view must be strongly typed to a model. So one solution would be to deserialize this JSON into a model object before passing it to the view:
public ActionResult ListPackages()
{
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
//code goes here ....
var model = new JavaScriptSerializer().Deserialize<MyViewModel>(json);
return View(model);
}
}
where MyViewModel would of course reflect the JSON structure that you are working with.

How can I accept JSON requests from a Kendo UI data source in my MVC4 application?

I am using the Kendo UI grid in my MVC3 application and am quite pleased with it. I am using a Telerik provided example, excerpt below, to format the data posted by the grid's DataSource ally, and all is good. However, I don't want to have to rely on code like this. I would like to get Kendo and MVC talking without the 'translator', i.e. this code:
parameterMap: function(data, operation) {
var result = { };
for (var i = 0; i < data.models.length; i++) {
var model = data.models[i];
for (var member in model) {
result["models[" + i + "]." + member] = model[member];
}
}
return result;
}
This function is a 'hook' that allows me to manipulated data before Kendo ajaxes it out. By default, the Kendo DataSource sends content-type form-encoded, but not quite right for the MVC model binder. Without this, I can still use a FormCollection and do my own binding, but that is not on.
When I configure the DataSource to send JSON, and change my mapping function to look like this
parameterMap: function(data, operation) {
return JSON.stringify(data);
}
I get the following data being send in the request, but now I have no idea how to get MVC to bind to this. Right now my only hope is to grab Request.Params[0] in the action method, and deserialize this JSON myself.
I don't think I should have to write any code to get two HTTP endpoints to communicate properly using JSON in this day and age. What am I doing wrong, or, what should I be looking at on my side, i.e. the receiver of the requests. I would really prefer to minimize my intervention on the client side to maybe just the stringify call.
No idea if this is still a problem or not since this is a rather old question, but I had a scenario where I was shipping up json data to my controller and I had to give it a "hint" on what the name was so that model binding would work correctly:
public JsonResult GetDatByIds([Bind(Prefix="idList[]")]List<Guid> idList)
In my scenario, kendo was serializing my data and giving it a name of idList[] in the form post rather than just idList. Once I gave it the model binding hint, it worked like a charm. This might be the same for your scenario.

In MVC3 how do I have a dropdown that shows/hides fields based on the selected value?

I have a dropdown of countries, and an address form. Depending on the country selected, I want to hide/show certain fields. I'm quite new to MVC and MVC3, what is the best way to do this?
I have on the page a 'DropDownListFor' that populates correctly. When this changes, I imagine I need to ask the server which fields to show/hide. I could perhaps put some JQuery into a change event that calls a method, and it returns some json saying visible:true for each field, but I don't know if that's ideal or even how to implement it (possibly $.ajax or something).
Any ideas?
Edit: I should add the hard part of this is asking the server what fields to show for each country as there are many countries and the possibilities are all stored in the database. I am accustomed to webforms not MVC so I would ordinarily postback and have serverside logic, but this isn't an option with MVC afaik...
I have deleted my first answer as it was irrelevant.
With MVC3 you can send an AJAX request to any method.
In HomeController.cs:
public List<string> GetFieldsToShow(string id)
{
// if you routing is left to default, the parameter passed in will be called 'id'
// Do what you gotta do...
List<string> listOfFieldsToShowBasedOnCountry = GetList(id);
return listOfFieldsToShowBasedOnCountry;
}
And in the AJAX call, something like...
$.ajax({
type: 'POST',
url: '/Home/GetFieldsToShow/' + valueOfSelectedDropDownItem,
/*etc...*/
success: function(data){
$(data).each(function(){
$('#' + this).show();
}
}
});

Asp.Net MVC Passing an object from Url.Action in View to Controller

While there appears to be similar questions I do not believe I found one where somebody was passing the entire model from view to controller, the closest I found was passing a data value in the model to the controller... which is not what I want to do...
I want to pass the model object to the applicable controller action result as a parameter
and do what I want to do with the data in the model object from within the controller...
code abbreviated...
in the view i am using Url.Action(string, string, object) to pass the controller method name, and the route to it as the 2nd parameter, and the entire model object as the 3rd parameter...
my third parameter is the problem, the Url.Action(string, string) over load works fine with the same values, so I don't have any problem getting to the controller action result method, with the values I am using...
view code snippet...
$('#ControllerActionResult').click(function (e) {
window.location = '<%: Url.Action("ControllerActionResult", TheRoute, new { pModel = Model } ) %>';
});
controller code snippet...
public ActionResult ControllerActionResult(object pModel)
{
}
My error is "CS1502: The best overloaded method match for 'System.Web.Mvc.UrlHelper.Action(string, string, object)' has some invalid arguments" and the window location line is highlighted...
Am I missing something obvious?
I don't think you can do that. Url is trying to build a url, not call the action method directly. You can pass individual key value pairs via the anonymous object, which Url can then use to build a link. Model binding can take care of putting the key value pairs into the incoming model for you.
Also, is TheRoute a string as well?
If you need a Url you don't have many alternatives. Either pass all the values to rebuild the model, or just pass a key value to retreive the model from the database again (or maybe session / viewdata / tempdata, if you're using that).
There might be several issues in your code. But I will answer what you want to know, how to send data to controller from js. You have to first send "model" in json format, possibly with jquery.ajax. For example,
$.ajax({
url: '#Url.Action("ControllerActionResult")',
type: 'POST',
data: JSON.stringify(model),
dataType: 'json',
processData: false,
contentType: 'application/json; charset=utf-8',
success: OnSuccess
});
In controller, you have to have a defined class for the "model" and that should be the parameter of your controller.
[HttpPost]
public ActionResult ControllerActionResult(Model model) {
if (Request.IsAjaxRequest()) {
//to do
}
}
Otherwise, MVC cannot find a right controller to call.
try with following code it works for me
Javascript:
var location ='#url,action(string ,obj)'; window.location=location;
Controller:
public ActionResult index(string obj){return view();}
hope this works for you.

Resources