I have a controller ItemsController that has an instance method GetRecent() which returns IQueryable<Item>
In the index page of my application I want to render a partial view _Recent.cshtml using the results from ItemsController.GetRecent()
To do this, I've written the following in my Index.cshtml
I've added namespace references to the ~/Views/web.config so I don't need to write out the controllers full namespace
#{
ViewBag.ItemsController = new ItemsController();
}
...
#Html.Partial("~/Views/Items/_Recent.cshtml",
((ItemsController)ViewBag.ItemsController).GetRecentItems())
I thought of passing new ItemsController().GetRecentItems() directly or turning GetRecentItems() into a static method however I'm not sure what direction this should take.
I want to know if this is an accepted way of building a partial view from a controller and if not, how can this be accomplished more efficiently?
RenderAction
The first option is Html.Action or Html.RenderAction(What's the difference?). These are part of the ASP.Net MVC framework, and provide a more polished means to implement something similar to your code sample.
With this approach, your view calls the appropriate controller, which fetches any needed data, renders the partial view, and returns it.
I tend to shy away from using this approach as it seems backwards, i.e. the view "knows" quite a bit about controllers and controller structure and is actively executing rather than just consuming.
Still, it's a legitimate option.
Remodeling
You could pass the "recent items" along with the view model for the main view. This is more effort to model, but "pure" in that your view is less coupled to the controllers. Your partial view would not need to change.
Async Rendering
You could render the recent items using an AJAX call to the appropriate controller, and have that controller return the partial view as its result. This is probably the most effort, but elegant in that some of the work is delayed until the rest of the page is rendered (possibly allowing lazy loading, and/or improved page load times).
Done correctly, this approach also allows decent separation of concerns.
Related Question (not identical, as it doesn't focus on passing data to the partial view)
Related
I decided to try avoid view models and pass dynamic data to views, here is the test code I wrote in my controller:
dynamic model = new ExpandoObject();
var user = unitOfWork.UserRepository.Get().First();
model.Title = "Dynamic test";
model.User = user;
return View(model);
And in View:
#Model.Title
#Model.User.UserName
I like this method more because I don't have to write ViewModel class for every controller action, and also don't have to change ViewModel every time I decide to pass a new property to View.
The only downside I see is lack of intellisense in Views, because they are not strongly typed any more, but that doesn't seem as a big problem.
My question is, is there any other downsides of using this approach instead of ViewModels, because I am just starting a new project in my company, and I don't want to regret later if I use this approach...
I believe that the main advantage of creating view models is readability and resuseability of the code.
If I go to your piece of controller which you pasted, technically I can understand it, but I don't know what the model is about from business perspective. Of course you can name it more descriptive, but I don't believe it resolve the issue.
Second thing is reuseability, so I can imagine a lot of situation when multiple views can use the same model or some part of models and in this case you need to copy & paste code which creates you dynamic model or create some helper function which do this for you.
Basically I believe that it will be very painful when those dynamic models need to be changed e.g you removed some property in controller, but you forgot to do the same in some of the views. You won't be informed by compilator that something is wrong.
Additionally without strongly typed view model I believe there is no way to create attribute based model validation (which is very common business case)
The code in View,
#{
var MyModel = Entity.Employees.Select(t=>
new {t.FullName, t.Department.DepartmentName}));
}
#foreach (var e in MyModel ) {
<div> Name: #e.FullName - #e.DepartmentName </div>
}
Controller is empty
public ActionResult Index()
{
return View();
}
I am new to Asp.net MVC. Here is something I learned from book.
Controller retrieves Model data, pass it to View
View consumes Model data
Use Strongly-typed model whenever possible
In controller, when model data is from EF/LinQ query, the type is often anonymous, not strongly-typed when passing to view. On the other side, I want to avoid generating one-time-used strongly-typed model.
Above code retrieves model data from View, it's anonymous-but-strongly-typed. seems I can get benefits from both side.
My question is: Should I populate model data from a view? If No, Why?
I found this helpful: it passes dynamic data between controller and view, it's fluent, but not strongly-typed
No, you should not.
You can read any of the articles online that tell you why MVC is a good pattern. You'll find that you have more opportunities for code reuse, unit-testability, etc.
If you're not using the controller to pass a view model to the view, then you're not really following MVC. You might as well be using Razor Web Pages.
Think of Skinny Controllers, Fat Models and Dumb Views.
Views should contain as little logic as possible. As the view model is created specifically for a view, the only responsibility of the view is to render itself using the view model's data that was created in the controller. If there are a lot of decisions, conversions or other logic in your view, then you are not really using the MVC pattern properly.
So as to your question: create your model in the controller, not in the view.
Thanks for all the good answers, they are right.
But my recent experience tends to say Yes... Only In Certain Case,
My project has a number of grid pages. The sole purpose is displaying some grid data. it is often
Not reused elsewhere.
Not needed a Unit Test.
Often asked to add/delete/change columns
Unit Test -- the Grid data is directly from an entity framework, basically a SQL query, There is no need to unit test a SQL query. (a stored procedure may need).
Change Handling -- it literally takes minutes to make an entity query change, bind to an column, right click the cshtml file & publish to production, all in one file. Asp.net will dynamically compile it.
Performance -- the project is a line of business application. Application performance has not been an issue, whereas programmer's productivity is importance, this approach does not lose any strongly-typed checking, auto-completion, etc.
I'm pretty experienced with Web Forms, but attempting a site in MVC to broaden my skill set. In Web Forms, you could do something like this to execute some JavaScript when the page loads:
ScriptManager.RegisterStartupScript(this, this.GetType(), "unique-script-id", "alert('Data saved.');", true);
What is the equivalent way to do this from a Controller? Should I pass a JavaScript block in the ViewBag, then in my View check for the existence of that script and render it? Or should I abandon the idea of doing this from my controllers and instead use AJAX from the client side to post the form to a Web API, and then based on the HTTP status code display the appropriate message?
public ActionResult Submit(ArticleModel article)
{
//save model to database
//I think here I want to do the MVC equivalent of registering a startup script providing a success message.
return RedirectToAction("Index");
}
What is the equivalent way to do this from a Controller?
You don't. Not from the controller anyway.
JavaScript is part of the view. The controller provides a model to the view, nothing more. It shouldn't be coupled to the view in any way. Your JavaScript would be invoked within the view.
If you're looking to conditionally include JavaScript in the view, you can wrap it in a conditional check on a model property:
#if(Model.SomeBooleanProperty)
{
<script type="text/javascript">
// your script here
</script>
}
Then the model would be logically determining whether or not that functionality is invoked. The view is simply binding to the properties on the model.
Edit: Another approach, structurally similar but without adding a property to a model, is to use something like ViewBag. In your controller you'd set the value:
ViewBag.SomeBooleanProperty = true;
Then you'd check it in the view:
#if(ViewBag.SomeBooleanProperty)
{
<script type="text/javascript">
// your script here
</script>
}
Keep in mind, however, that this introduces some coupling between the controller and the view. The view now assumes that something other than the model has been set. It then becomes the responsibility of any code which returns that view to explicitly set that value. Models are a way to enforce this more explicitly, eliminating the coupling.
Additionally, you seem to be misunderstanding something in one of your comments:
This information I'm talking about isn't data, so it doesn't belong in the model.
Models don't contain just data. Models contain the core business logic of your application. Just data results in "anemic models."
Learning the "MVC Way" of doing things will help you in the long run to develop more modular, testable applications.
In your example, you are wrapping your functionality around multiple components. You are wanting your controller to tell your view to perform some action. This is the practice that MVC frameworks in general strive to deviate from.
MVC frameworks, including ASP.NET MVC, adhere to the principal of least responsibility.
The job of your controller is to Control your application flow. It isn't even really responsible for program logic, you will likely have Services to handle things like Database management, complex calculation, etc. Your controller shouldn't really care about the view, or how the view displays information; it should only care how to make a view and tell the view to do it's thing. Typically, controllers can be slimmed down to less than 10 lines of code in all but extremely complex scenarios.
By the same token, the view shouldn't care how the controller works, or the services that the controller responds to. Views should never be told how to display information, errors, etc, only given data or a status to work with.
Keeping this separation of concerns means a few things. First, it ensures that you can make changes to one part of the application without it having a major impact on another portion. Secondly, you can test if the controller is working without ever having a view, and you can render the view with sample information without a functional controller. This makes your development team much more efficient.
Bottom line, you should keep the idea of Separation of Concerns in the front of your mind when working with MVC, and if you are ever thinking that you need to have your controller tell the view to show something, you are probably going the wrong direction with your overall architecture.
Hmm..
You can directly use javaScript in CSHTML and if you want to show your script under condition than you can bind it inside if condition just pass a signal from controller to show your script only
true or false
EXAMPLE
set a boolean value from controller and keep in ViewBag
ViewBag.isSubmit= true;
and then check condition in your view
#if ((bool)ViewBag.isSubmit==true)
{
<script>
alert('Submit Successfully');
</script>
}
but remember to insert # before if because this is CSHTML and uses Razor syntax.
I've just joined half-finished project and I'm faily new to asp.net mvc.
I've noticed that the project has fair amount of controllers and also they're accompanied by even greater amount of views.
So the problem is many of these controllers extract data from the db and call a _*controllername*TableResult.cshtml view to render it (it's a partial view).
Now these views are very VERY similar and I find this code repeating somehow annoying (for creating new views). The problem I've found so far is that you have to pass the model
#model List<GroceriesTableModel>
There're some other differences like - ajax(actionName, controllerName) and id`s of the html - but all these can be fixed with a Dictionary?
My question: is there a way to somehow template these look alike views - and pass the correct model and a Dictionary object for the id`s?
Sure is - #Html.RenderPartial("_partialview", model, Dictionary)
search renderpartial for more details...
I have a partial view that loops through its Model (a list of things) to show the thing.Name and three integer values that are counts of related entities.
First of all, I tried putting: (pseudo-razor)
foreach(thing in Model){
#thing.Name :
#thing.related.entities.where(condition1).Count()
#thing.related.entities.where(condition2).Count()
#thing.related.entities.where(condition3).Count()
}
But its really slow... so I created a function in the ThingRepository that does same queries faster, something like this (pseudo-code)
function GetCountofRelatedEntities(relatedID,condition){
return db.entities.where(relatedID==relatedID && condition).count()
}
and its much faster, so I want to call it. I think I should call it from the controller, but then I need a ViewModel to keep a (thing, int, int, int) collection as the model, or I can use the ViewBag extremely to pass the results to the view, but, and here is the question:
Why not simply use the repository from the view? whats wrong with this code in the view? (pseudo-razor)
#repo=new ThingRepository()
foreach(thing in Model){
#thing.Name :
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
}
Could you tell me why I shouldn't instantiate the repository inside a View? Or I can do it?
Why not simply use the repository from the view?
Because you are violating the MVC design pattern. A view's responsibility is not to fetch data. It is to display data that it is being passed to it from the controller under the form a view model. And it's as simple as that.
You could call repositories or whatever you like in your views but just don't tag your questions with asp.net-mvc anymore because you are no longer doing any MVC. I mean you could do whatever you like - you could even write SQL queries in your view if you want.
But the whole point of the MVC design pattern is to separate the data retrieval logic from the presentation logic.
One purpose of the MVC pattern is to provide a structure that fits a wide range of common programming situations. To simplify:
Model: Describes the shape of your application, i.e. the parts of your software specific to your business.
View: Display the data to the user and transmit user events to the server.
Controller: Acts as a middleman between the view and the model.
What you're proposing "works," in the sense that it gets the data on the page where you want it. In the short term, it appears to be saving you time and effort, as you don't have to bother with controllers, viewbags, etc.
However, you are breaking the MVC structure in a way that you will probably regret later on. For example, say in a few weeks your boss comes to you and says, "Hey, you know that page you added to display that list of entities? We need to do some filtering and sorting on it. And I need it yesterday."
Now you're faced with a choice: Do I add this filtering logic to my view page and meet the deadline, or do I take the time to move the data access code to a controller and rework my view, at the risk of missing the deadline and breaking what's already working?
You'll probably take the easy way out and add the logic to the view, and now you've got a growing mess on your hands. We've been down this road with VB6 and Webforms apps with 6,000-line codebehind files. Trust me--you don't want to go there.
Another problem is that the MVC structure is well understood by the programming community. If someone else comes along and tries to work on your code, you're making it harder for them by deviating from the conventional approach.
The MVC structure is time tested and sound. Until you fully understand its purpose and the benefits it provides, try to follow it closely. It's not a good idea to break the rules until you have a firm grasp on them.
My main objection would be the separation of concerns. Once you start hitting your DB from your view, your "view" really isn't just a view anymore. It's really handy to have a clean separation between your data access and your view.
Why is this separation of concerns important? It makes it easier to work with systems that are composed with these clean separations. When you need to adjust what data is retrieved, you'll never need to fuss with the view. So long as the view gets the right value, it will display it correctly. Likewise, if you want to change how values are displayed, you can modify the view without any chance of borking the data.
The thing is that you should not have any logic in your View because this is not the MVC approach.
MVC is Seperation of concern.
So you should create your ViewModel wich contains ALL the data your View needs.