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.
Related
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 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)
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.
I'm new to MVC / MVP and learning it by creating a Winform application.
I have to some extent created the Models, Presenters and Views... Now where do my validations fit.
I think the initial datatype validation (like only numbers in Age field), should be done by view. Whereas the other validations (like whether age is within 200) should be done by model.
Regarding datatype validation, my view exposes the values as properties
public int? Age
{
get
{
int val;
if (Int32.TryParse(TbxAge.Text, out val))
{
return val;
}
return null;
}
set
{
TbxAge.Text = value;
}
}
I can perform validation seperately, but how do I inform presenter that validation is still pending, when it tries to access the property Age ?. Particularly when the field is optional.
Is it good to throw a validationpending exception, but then the presenter must catch it at every point.
Is my understanding correct, or am I missing something.
Update (for the sake of clarity) : In this simple case where the age field is optional, What should I do when the user typed his name instead of a number. I cant pass null as that would mean the field has been left empty by the user. So how do I inform the presenter that an invalid data has been entered...
Coming from the MVP side (I believe it's more appropriate for WinForms) the answer to your question is debatable. However the key for my understanding was that at anytime you should be able to change your view. That is, I should be able to provide a new WinForms view to display your application or hook it upto a ASP.NET MVC frontend.
Once you realise this, the validation becomes aparant. The application itself (the business logic) should throw exceptions, handle errors and so forth. The UI logic should be dumb. In other words, for a WinForms view you should ensure the field is not empty, or so forth. A lot of the properties for the controls allow this - the properties panel of Visual Studio. Coding validation in the GUI for the likes of throwing exceptions is a big no no. If you were to have validation on both the view and the model you'd be duplicating code - all you require is some simple validation such as controls not being empty for example. Let the actual application itself perform the actual validation.
Imagine if I switched your view to a ASP.NET MVC front end. I would not have said controls, and thus some form of client side scripting would be required. The point I'm making is that the only code you should need to write is for the views - that is do not try to generalise the UI validation across views as it will defeat the purpose of separating your concerns.
Your core application should have all your logic within it. The specalised view logic (WinForms properties, Javascript etc...) should be unique per view. Having properties and interfaces that each view must validate against is wrong in my opinion.
If your "view exposes the values as properties", I suspect that you are missing something. The principal distinction between MVP/MVC and some of the other UI decoupling patterns is that they include a model, which is intended to be the main container for data shared by the view and presenter or controller.
If you are using the model as a data container, the responsibility for validation becomes quite clear. Since only the presenter (or controller) actually does anything besides display the data, it is the one responsible for verifying that the data is in an acceptable state for the operation which it is about to perform.
Addition of visual indicators of data validation problems to an editor form/window during editing is certainly nice to have. However, it should be considered more or less equivalent to view "eye candy", and it should be treated as an add-on to the real validation logic (even if it is based on shared metadata or code). The presenter (or controller) should remain the true authority for data validity, and its validation code should not be hosted in the view.
I believe view validation is only relevant in javascript as the view does not run any code on post, only the controller does.
But I would also not ever trust javascript validation as a malicious user could bypass it or an ignorant user might have JS disabled so repeat any JS validation in serverside code in the controller.
The view might have means to display any errors though .
I am newish to MVC and understand all the great things about it, including the reasons why viewstate isn't available, however there are some circumstances where I think having some kind of view state will be quite handy, In my case I am thinking about list pages with various search filters that can be applied to the list.
Would it be worthwhile implementing some kind of pseudo viewstate to hold this info in some cases? or is there a better solution?
Any examples out there?
Your comments appreciated.
In ASP.NET MVC, state-retention is typically handled by round-tripping the state information back to the view.
For example, in the NerdDinner CRUD examples, they show how you can submit a form, check for errors, and if there are errors, display the form again with the data still intact, including the necessary error messages.
This works because the controller method handling the POST simply passes the data back to the view:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
Dinner dinner = dinnerRepository.GetDinner(id);
try {
UpdateModel(dinner);
dinnerRepository.Save();
// No Errors, return to detail view
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
foreach (var issue in dinner.GetRuleViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
// Errors, display form again. Pass state information back to form.
return View(dinner);
}
}
The theoretical answer
ViewState is one of the concepts of ASP.NET WebForms which is considered VERY harmful. It is used to store the state of some controls and renders a very-VERY ugly hidden field into the HTML.
This is undesirable for some people for SEO (search engine optimization) and other reasons.
MVC doesn't provide some of the abstractions that WebForms does, for some very basic reasons:
It gives you full control over your URLs and output HTML
WebForms controls (especially the "advanced" ones) render junk HTML, MVC lets you write your own HTML
In order to avoid these faults, MVC doesn't use the principle of controls, events, and such stuff
If you wanted your web framework to abstract away the REAL way HTTP behaves, you should continue to use WebForms
In truth, HTTP is a stateless protocol, which WebForms try to hide from you by introducing the concept of Controls, and their state and events.
MVC doesn't lie to you and doesn't try to hide anything from you.
The practical anwser
You can use ViewData instead of ViewState.
You set an item (ViewData["Something"] = yourObject) in the Controller, and then you can retrieve it in the View. You can use it to "remember" whatever you want it to.
So, basically, persisting the information consists of reading it from Request.QueryString or Request.Form in the appropriate Controller action, setting it into the ViewData, and then retrieving the ViewData information in the View.
For example:
Controller action:
string textBoxValue = Request.Form["myTextBox"];
...
ViewData["myTextBox"] = textBoxValue;
View:
<% using (Html.BeginForm()) { %>
<%= Html.TextBox("myTextBox") %>
<% } %>
More stuff
Read some MVC-related questions here (such as this one), and read the MVC book (at least the free NerdDinner chapter).
MVC will be much more understandable for you then, I promise!