My website is built around tabs. I have one single page with multiple partial views that display each tab.
The problem im facing now is I want to loop through files that the user has uploaded and display them in one of my partial views. This requires me to send the file list as a paramater in my action like this:
//Uploadedfiles is a function that adds the files to a list.
var files = UploadedFiles();
return View(files);
Because im only using one view to display all my partial views, i get:
The model item passed into the dictionary is of type 'Microsoft.WindowsAzure.Storage.Core.Util.CommonUtility+d__0`1[Delamapp.CloudStorageServices.UploadEntity]', but this dictionary requires a model item of type 'Delamapp.Models.LoginFolder'.
This means im required to not send a model item to my index view. Now, the only thing i can think off is adding my file list to viewbag and then display them on my view. BUT.. The files require high security. How safe is viewbag? Can you for example store sensitive login information in there? Can you think off some other way to accomplish this?
Thank you in advance
You can pass a model item to your view, but the model item you are passing doesn't match the type of model that your view uses (that's what the error message says).
So you need to do one of the following:
Modify your view to accept the model type that you are passing to it
Put the data you want to pass into the model type that your view is expecting
Create a new model type for both your data and for the view, and use that
In terms of security, I don't think using a view bag versus model binding really enters into the question of security. Both are just ways of passing data in between the controller and the view, and that all takes place within the ASP.NET process (perhaps you have ViewBag confused with Web Forms' ViewState?).
Related
I've understood that a viewmodel in MVC is supposed to reflect data on a single page rather than objects in the model. But should the viewmodel correspond to the data you want to show on that page or to the data you want back from that page? If we for example look at a login page then I just want username and password back in the post, but I might need more variables than that when displaying the login page (previous error messages etc).
Should the viewmodel then just contain username and password as parameters and the rest of the variables end up in viewbags. Or should the viewmodel contain all values I want to show even though I'm only interested in a few of them in the response.
What is best practice when using viewmodels?
All data that somehow interacts between the html and your server should be in a ViewModel.
This allows you to perform formatting and such outside your html and inside your ViewModel properties.
However, if your page contains a lot of controls or data, you may want to split it into multiple ViewModels (example one for the Get and one for the Post).
The post model may contain only data that you entered and needs to be validated.
I think it's best to put everything in the view-model. This keeps the code cleaner and makes discovery and maintenance easier as well. The view-model should be your primary mechanism here.
I would say only properties you need, in your case username and password. If you want to display error messages then that's what ModelState is for. You can always append any error messages to your ModelState:
ModelState.AddModelError("PropertyName", "Error Text")
Beyond that let's say you have a form that contains a list of categories that you need to pick one category from a drop down. In this case I usually attach that list to my model even though the only thing being submitted is the actual selected value. But this is a matter of preference, meaning I could also set a ViewBag to contain this SelectList of categories and then bind that to your DropDownList. I suppose it's better to place this in a model because ViewBag is dynamic and you will have to cast anything in the ViewBag into it's underlying type on your views.
I'm in serious need of passing url params with View class. Here's code:
if (!ModelState.IsValid)
{
return View(model);
}
This should not only return model based view, but also add specific param to URL (param won't change view details, but is needed as it's one of few automatically generated SessionKeys (one for each tab/window used to view app) and I know no other way to get to it, different than passing as param (it can't be generated everytime, 'cos params will change; it can't be global variable because it'll reset its value each refresh; it can't be static, because static is evul).
Oh this action is called with use of form and submit button, not actionLink or something like this.
EDIT1: I need params to stay in URL after refresh, or I need some other form of keeping data that persists through refresh/validation fail.
If I understand you correctly you have data that you need to use in generating Urls on your page? This just forms part of your ViewModel - or at least it should, since it's data that the View needs in order to render.
You can use ViewData to add any extra data that isn't part of your view model. Or, better still, add the data as members to it. Equally, if different views with different View Models require this data, add a ViewModel base class and derive from that so you can share that data.
use
RedirectToAction("actionName","controller",
new RouteValueDictionary(new {param1="value",param2="value2"});
or you can use hidden field to store the values in your page and then pass this down as and when you need them..
When a model is passed to view, the view has access to all data inside that model. But only for first time. When the view page is submitted say by clicking a submit button , then you don't get any data in the controller. For this you need to explicitly bind each and every model item either by giving a control to populate it or by using Html.HiddenFor(..)
But if my model is having a collection member which in turn having collection member .. upto level 3 or 4, then do I "have to" bind each and every member of these collections in order to get all data in action method after submit? If I am not displaying all these collections items on a view, then why should I bind it by writing huge code? But then I need them in the action method too. Is there any other simpler way to accomplish this other than explicitly binding it on view?
Following is the structure I have.
SalesModel
....IList HomeProducts
....int SalesID
Products
....int ProductID
....IList SecurityProducts
SecurityProduct
....SecurityProductID
....Description
....Price
....IList ProductFeatures
~ SalesModel is boud to aspx (View).
~ From this view, I have called partial view to show Home products (with model=Product).
~ From this partial view I have called another partial view (with model=SecurityProduct).
~ When I first time open the view, I get data at every level. But when I submit the view using submit button, then I dont get anything in SecurityProduct collection evern after binding every thing in FOR loop.
Thanks in advance.
yes, great example here: http://weblogs.asp.net/nmarun/archive/2010/03/13/asp-net-mvc-2-model-binding-for-a-collection.aspx
Resolved : by having hidden fields on both, the root level aspx and the child level ascx. Don't know how this resolves it but it solved the problem.
I have an asp mvc 2 app lication where I want to display a list of check boxes that a user can select, based on a list of records in a database. To display the list my model contains a List object and the view has a foreach, and outputs Html.CheckBox for each item in the list.
Is there a way to get the model populated with the selected checkboxes, given that the model can't have specific properties for each checkbox, because the list is dynamic? Or do I have to manually iterate through the forms variables myself?
Edit: Extra details as per sabanito's comment
So in a simple view/model scenario, if my model had a property called Property1, then my view outputted a Textbox for Property1, when the form is posted via a submit button, the mvc framework will automatically populate a model with Property1 containing the text that was entered into the textbox and pass that model to the Controllers action.
Because I am dealing with a dynamic list of options the user could check, I can't write explicit boolean properties in my model and explicitly create the checkboxes in my view. Given that my list is dynamic, I'm wondering if there are ways to create my model and view so that the mvc framework is able to populate the model correctly when the form is posted.
Here's what I would do:
Are you having any issues generating the checkbox's dynamically?
If not, create a property on your ViewModel that is a:
public List<string> CheckboxResults { get; set; }
When you generate your checkbox's in the view make sure they all share the name = "CheckboxResults". When MVC see's your ViewModel as a parameter on the action method it will automatically bind and put all the "CheckboxResults" results in the List (as well as your other ViewModel properties). Now you have a dynamic List based on which checkbox's your user checked that you can send to your DomainModel or wherever.
Pretty cool stuff. Let me know if you're having issues generating the checkbox's dynamically, that's kind of a seperate issue than model binding to a list.
Use a ViewModel that reflects your view exactly, and map your domain model(s) to the viewmodel.
At first it often seems appropriate to use domain models directly in the view, for no better reason than that they're simple to use. However, as the view gets more complex over time, you end up putting a TON of conditional logic in your view, and end up with spaghetti. To alleviate this, we typically create a ViewModel that correlates 1:1 with the view.
We are beginning the process of moving from Web Forms to MVC for all of our new applications. I am working on porting our Master Page over and am trying to satisfy the requirements that we need a single master page to be used by all applications. The primary navigation for the application needs to be in a menu within the master page. Accomplishing this was easy, the hard part is that each application may need to determine what to display in the menu using a unique set of rules. Some apps can simply say, here's the menu structure to use via something like a SiteMap. Others need to determine what is displayed in the menu based on what roles the user has, this can also be handled easily with a SiteMap. The situation that I'm struggling with is that some apps need to generate the menus based on the roles the user has, but also on the data on which they are working. i.e. The same user may have different option in the menu for a page if they are working on object 'foo' than they do if working on object 'bar'.
What I've done at this point, is I've created an HtmlHelper that is called by the master page view and takes a list of objects of a custom type and returns an unordered list that is styled by a jQuery plugin to display the menu. The list of objects the helper method takes are passed to the view using the ViewData dictionary. Currently, the value of this ViewData node is set within the constructor of each controller. This allows each page, and potentially each method, to set a different menu without having to set the value in each action method, unless its needed. I have also created a class that parses a SiteMap and returns the list of items needed to build the menu. This class is what I'm using to set the ViewData value in the controller. The idea being that if an application needed more control of how the menu data was generated, they could create their own class to generate the data as long as it returns a list of the correct type of objects.
This solution seems to work fine so far, it just doesn't 'feel' right for some reason. I'm hoping that I can either get some ideas of better way to do this or some reassurance that this is a valid approach to solving this problem.
If it is something that will be on every page, do something like this:
Create a base controller:
public class MyBaseController : Controller
Have this controller get the data it needs and send that data in the ViewData["menu"] to the View. Then have all your controllers inherit from this one:
public class HomeController : MyBaseController
In the Master Page, loop through your ViewData and create your menu.
(I did something like this for my sub-menu which displayed a list of categories.)
In the book I am reading (Pro ASP.NET MVC Framework by Apress) they use Html.RenderAction for the menu in the masterpage. I am a Asp.net MVC novice so maybe somebody else can give more info about this.
You can download the sourcecode at apress.com though so maybe that could help.