For some reason this line of code.
#Html.DisplayFor(modelItem => item.api_name)
is throwing the error.
Compiler Error Message: CS1963: An expression tree may not contain a dynamic operation
Web search has been no help I can't seem to figure out whats wrong with the code.
The page is not strongly typed.
As the error states, you can't use dynamic models with type-safe editor helpers.
You should use typed models instead. (using #model SomeType)
Is your view strongly typed? If not, you need to have a strongly typed view, as lambdas don't support dynamic members.
Just add this to the top of your view:
#model YourModel
Related
Which is better from design and coding point of view: accessing session data in the view directly or loading them in the controller and passing them to the view using a viewbag?
MVC wont really care if you do something in your controller or your views but i agree with shaftpolls for not hurting the mvc pattern. Since Session is already inside the ViewData wrapper, you can access it directly in the View.
Be aware, that the Session object should only contain simple, non-sensitive data like user picked language, or custom ui-colorsheme.
If you really need to use Session, you should get that data on the server side and then pass it to the View using Strongly Typed properties in a View Model rather than using the ViewBag.
So let's say you have a property on your view model which is of type IENumerable<SelectListItem> and inside your view you will use the strongly typed version of the Html.DropDownListFor helper to bind to the model this way:
#Html.DropDownListFor(x => x.ProductId, Model.Products)
The best thing to do is access the session in the controller. Why:
Performance. You have fine control of how to access the Session object. If you need to read just properties of the session, then specify that you need read-only access to the session, MVC won't block the session, you'll get more performance.
Pureness. In a pure MVC scenario, the view knows only about the model. So any value that you care about in your session must be passed as part of the model.
I am new to asp.net mvc4 and there is something i don't understand well.
Why do I have to declare the Model using #model at top of the view, if I already pass an object to the View in the controller.
Taking an example :
Controller:
public ActionResult countryDetails(int id)
{
Country country = db.Country.Find(id);
return View(country);
}
View:
#model MvcApplication2.Models.Country
#{
ViewBag.Title = "countryDetails";
}
...
The controller returns a View with an object as parameter, so the model should be already known. I'm sorry if it is obvious, but I can't figure out why this is not a "double" declaration.
Thanks for you help !
The declaration at the top will do two things for you:
It will allow intellisence to know what type you are using when you type in #Model or use any of the Html helper extensions.
It will also check at runtime that model passed in can be cast to the type the view expects.
Its not necessarily a "double declaration" as it is analogous to specifying a type to a parameter on a method. Like so
Person Someone = new Person();
RenderView(Someone);
...
void RenderView(Person model) { }
By default your view inherits from System.Web.Mvc.WebViewPage<TModel>
You can optionally override this class, it's default ASP.NET inheritance mechanism:
#inherits System.Web.Mvc.WebViewPage<List<CompanyName.MyProduct.MyCategory>>
Or you can just simplify this since MVC3 like this:
#model List<CompanyName.MyProduct.MyCategory>
This sugar syntax was made to simplify code typing.
This declaration give you some things
View automatically cast object to the preferred type
You receive type-defined 'model' property which allows you to access
to your object methods and properties
Just believe that this is a method which accepts object and cast it to the specified type that you provide
The main reason is type-safety, it allows you to work with strongly typed views with the benefit of intellisense, compiler error hints, invalid casting etc.
Also, another reason is for readability - it acts as a reminder to what sort of model it is you are actually dealing with instead of having to keep referring back to the controller.
I am using in my views (asp mvc3/razor cshtml) references to the Request object (eg, #Request.Params["Name"]). Do you think this is a very bad practice? Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Best practice is to use a model class. An instance of the model class is created or updated in your controller. Then the controller displays a strongly-typed view.
So I'd avoid direct access to the request from the view as well as the use of the view bag.
Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Yes. You will avoid runtime errors if "Name" does not exist.
The IDE will not warn you of the NullReferenceException about to be thrown with the following code.
#Request.Params["Fake"].ToString()
Of course, you'll have to be careful about ViewBag.Fake being null as well.
I like to use the viewbag to store things not related to the model, for example if I have a dropdown containing locations. I like to store only the id of the selected location on the model and the locations in the viewbag, since is not needed to create a contact. I think that's the purpose of the viewbag.
For me the model is a bag or properties used in business operations, for example if I have a customer creation view using a NewCustomerModel, I don't wanna pollute my model with things like a IList<CustomerType> AND a SelectedCustomerTypeId property. I just want the second since is the one imma use to create the customer.
There seem to be multiple means of passing model data from controllers in asp.net mvc to views. Its not clear to me if there's a recommended approach in the mvc v1 and v2 releases or if like most things in life, it depends. I've seen several approaches:
Option 1 - Populate the controller's ViewData dixtionary in either an icky string-based indexing way with casting in the view, or the in a strongly typed way by creating a strongly typed custom model class and passing that via ViewData.
Option 2 - Use ViewData.Model, which I'm not sure I even understand.
Option 3 - Use ViewPage.Model, in which case I'm not sure how you pass the model data from the controller.
I've seen a number of posts poo-pooing options 1 and 2 but I don't understand why. These posts seem to highly recommend 3 in most cases.
How do you approach this? Is there a standard way?
Every view 'should' have a specific model. This is sometimes more work so people use short cuts like ViewData, which works but is just not as clean and type safe in my opinion, so I prefer to have everything in the view's model.
You can then make all your views stongly typed. This is a very clean way to do so. Then in your controller you just call the view like:
YourViewModel model = new YourViewModel()
{
// initialize the data here
};
View(model);
Then in your views you can access all the data via ViewPage Model and it is all type safe and enforced from the controller as well.
EDIT from comments:
You don't need to use ViewData at all if you don't want. You can encapsulate all the data your view needs in a model. Just like the example you quoted with ProductsListViewData. It's just a model that contains all the items that were going to be stored in the ViewData. Both ways work but when you encapsulate it in a class (preferred method where everything is in the model) then all the bits and pieces are strongly typed.
ViewData is a generic container so even though you can just put anything you want into it, it is not type safe and therefore not as 'clean'. It comes down to preference and maintainability. There is only option 1 and 3. Your option 2 is misunderstood and is just option 3 in reality. There is no ViewData.Model just ViewPage.Model.
One approach you may wish to consider as your views become more complex, is to reserve the use of Models for input fields, and use ViewData to support anything else the View needs to render.
There are at least a couple of arguments to support this:
You have a master-page that requires some data to be present (e.g. something like the StackOverflow user information in the header). Applying a site-wide ActionFilter makes it easy to populate this information in ViewData after every action. To put it in model would require that every other Model in the site then inherit from a base Model (this may not seem bad initially, but it can become complicated quickly).
When you are validating a posted form, if there are validation errors you are probably going to want to rebind the model (with the invalid fields) back to the view and display validation messages. This is fine, as data in input fields is posted back and will be bound to the model, but what about any other data your view requires to be re-populated? (e.g. drop-down list values, information messages, etc) These will not be posted back, and it can become messy re-populating these onto the model "around" the posted-back input values. It is often simpler to have a method which populates the ViewData with the..view data.
In my experience I have found this approach works well.
And, in MVC3, the dynamic ViewModels means no more string-indexing!
This might be of some help:
When is it right to use ViewData instead of ViewModels?
(I know the following answer is highly arguable, but it's just the way I like to do it)
I would say use ViewData for simple data-tasks, and use the Model for the main purpose of the View. Check out Rob Conerys ViewData helper-classes here to give them a bit more Strongly typed feel:
http://blog.wekeroad.com/2010/01/20/my-favorite-helpers-for-aspnet-mvc
Using Models for absolubtely everything will bloat your project with hundreds of models just to achieve the smallest thing. I mean if you have a User-setting page, you would normally pass a User-model into the view, but if you decide to show some related data like Customers related to this User. You're stuck with the following solutions
You might have to add a List property to the User-model in order to expose the customers to the view. This leads to the Customer-property always being applied to the User-model everywhere else in the project - or make a new simpler User-model.
Make a new action that returns a partial of customers, which you can use with Html.RenderAction.
OR
you could do ViewData["Customers"] = myRepo.GetCustomersRelatedTo(user); // or something like that.
and (if using Robs helpers) in your view:
<%= Html.RenderPartial("CustomerList", Html.ViewData("Customers")) %>
add a PartialView called CustomerList that takes IEnumerable
In my humble opinion this is a cleaner solution and sure - you end up with a magic string here and there, but I'll stick to this approach until someone shows me a project with not a single magic string.
Use the tools we have in the Framework to get the job done. and Keep it simple s... ;)
I call the above line in my asp.net mvc view. How do i retrieve the dictionary values from the test controller?
You can pass information using ViewData e.g. ViewData["MyDictionary"] = myDictionary;
You can't. The point of RenderAction is to let the controller you're calling do what it normally would without you worrying about what's happening. Maybe a partial view might be better suited for you in your case, it's hard to say without seeing the big picture...