Does this really violate MVC Separation of Concerns - asp.net-mvc

Simple question. I must be totally wrong but I thought worth asking this question.
Is accessing ViewData[“Message”] within the View correct according to separation of concerns described in MVC?
For example, in Controller:
ViewData[“Message”] = “Display this message”;
Within View we call
<%= ViewData[“Message”] %>
The alternative (does not violates Separation of Concerns) is to have the Message set in the view model.
For example in Controller:
UserViewModel.Message = “Display this message”
Within View we call
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<UserViewModel>" %>
<%= Html.TextBox("Message", Model Message)%>
Any ideas greatly appreciated.

The difference between ViewData and Model is that the former is untyped property bag and the latter is a strongly typed object. But they both act as 'models' for your View.

I don't see how these should be different, other than the last one being strongly typed? You pass data along to the view, and let the view do its thing.

To me, I think the concept of all three (ViewData, ViewBag and TempData) is a violation of MVC. Very convenient to use but not following the diagram found here.
The View shouldn't know what the Controller is passing. I actually asked the same question just a few minutes ago and then I found this post.

Related

Purpose of viewmodel in controllers when data already present

What is the point in using a viewmodel when all the relevant data is already available through the parameter in the signature of the controller? I've seen a lot of examples similar to this:
public ActionResult Index(BasicPage currentPage)
{
var model = new BasicViewModel { Heading = currentPage.Heading, Body = currentPage.MainBody, MyBlock = currentPage.MyBlock };
return View(model);
}
Why not just send in the "currentpage" in this example directly to the View? Is there something that is considered bad practise by doing like that?
The above was a general question for asp.net-mvc. I'll add a question about Episerver as well here as well and if I'm lucky someone can answer that as well.
When looking through the Alloy site done with MVC I also saw similar behavior like above where a viewmodel is created in all controllers, why not just send in the Page that is sent into the controller directly to the View? It seems like an unnecessary step to create the viewmodel? Most likely I'm missing some important point here =)
The idea behind viewmodels is that they are optimised for presentation. If you use domain objects you end up having to put logic into the view itself to control the way things are displayed. Putting logic into the view is poor design so the viewmodel gives you some flex so that you have this logic managed in a more appropriate place.
In addition, you can make your viewmodel simpler, only including the fields that are required for the specific view.
Your code example is not a good idea I agree. But having a view model is a good pattern. You might not need it right away but having a view model available and in place is a good option to have for upcoming additions. I would go with Joel's concept from his MVC templates: http://world.episerver.com/Download/Items/EPiServer-CMS/EPiServer-7---CMS/EPiServer-7-MVC-Templates/

MVC, Strongly Typed Views vs Separation of concerns

I just got an example from a book
Controller:
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse)
{
// TODO: Email guestResponse to the part organizer
return View("Thanks", guestResponse);
}
View:
#model MvcApplication1.Models.GuestResponse
#{
ViewBag.Title = "Thanks";
}
<div>
<h1>Thank you, #Model.Name!</h1>
#if (Model.WillAttend == true)
{
#:It's great that you're coming. The drinks are already in the fridge!
}
else
{
#:Sorry to hear that you can't make it, but thanks for letting us know.
}
</div>
I believe that this approach is against concept of separating view and model / controller logic.
My approach is:
controller:
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse)
{
ViewResult v = View("Thanks");
v.ViewBag.Name = guestResponse.Name;
if (guestResponse.WillAttend)
{
v.ViewBag.Message = "It's great that you're coming. The drinks are already in the fridge!";
}
else
{
v.ViewBag.Message = "Sorry to hear that you can't make it, but thanks for letting us know.";
}
return v;
}
View:
#{
ViewBag.Title = "Thanks";
}
<div>
<h1>Thank you, #ViewBag.Name!</h1>
#ViewBag.Message;
</div>
The purpose of this "question" is to clarify that view should be used for viewing and controller for controlling what to show, and that a book example is "bad approach" (I'm considering the fact that the author just wanted to show abilities of MVC)
Now is using strongly typed Views (with logic code) really that good idea, or is it going back to sort of ASP spaghetti code?
Please give some good feedback considering high quality enterprise design
Update:
I know it's trivial example, there is no validation ans such, but would it be a good practice (for the sake of this example) to put the logic in the model, and then on the view just access the result like:
#Model.Message
Separation of concerns is not about coupling per se, but rather delineating who is responsible for what. Creating UI elements in the controller violates separation of concern, populating data does not. There is, of necessity, some required coupling between controller and view. After all the controller action MUST supply the data that the view uses to generate the UI. Generally I favor strongly typed views and model-per-view when doing MVC. This gives me the benefits of strongly-typed data in my view code. In practice, there is typically a mix of a strongly-typed view model coupled with some ViewBag data for cross-cutting concerns.
As far as using logic in views I would say "it depends." I've used separate views, a view that chooses between several partials (based on model data), control-of-flow to choose HTML variants. The choice of which method depends on how much differs between the models/views. If the logic is only around choosing UI display, I'm comfortable leaving it in the view. I'd much rather have that then push the choices back into the controller. That would violate separation of concerns.
Using code within the view isn't the same thing as having strongly typed views. You can easily have either one without the other. Strongly typed views have several advantages and is not in itself a violation of separation of concerns.
Using branched code within a view can be a code-smell, and may in fact violate separation of concerns, but that really depends on what the code is trying to do. In the case you presented, I would argue that it's not a violation since the string used in the view exists strictly for presentation purposes.
as tvanfosson explained succinctly, the Separation of Concerns comes from decoupling of Controller and View.
As opposed to web forms and asp classic, MVC architecture separates the logical layer (Controller) from the presentation layer (View). As long as the code for each is in separate locations, we have achieved Separation of Concerns.
The Model is a passive medium for passing information from the Separated layers. Making the model strongly typed tightens the "contract" between the 2, but doesn't violate the separation. Your data access method could evolve from ADO to ORM without ever having to re-visit the View Code. Your ORM could be refactored to use a web service without changing the View at all.
Only if you decide to change the incoming or outgoing values for the View would you have to alter the View. And that, at core, is Separation of Concerns.

Pass data to User Control ASP.NET MVC

I have a user control which shows list of latest announcements. This user control would be used in almost 90% of my pages. Now my concern is how to pass data to this user control for latest announcements.
My first approach is to make a base controller and in Initialise method I pass data to user control via ViewBag/ViewData. All my other controllers derive from this base controller. This looks nice but my concern is that it may become an overkill for some simple solution existing already out there. Also I would need to make sure that no controller ever fiddles with my Viewdata/Viewbag data meant for my usercontrol.
Please let me know if this is correct way of proceeding ahead or there exists some better solution.
Thanks
Assuming you have a "user control" (you should try to refer to them as partial view's in MVC) that looks like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Announcement>>" %>
This means your partial view expects a list of Announcement objects.
Now, the question is - where are you rendering this partial view?
You could be doing it from a master page, you could be doing it from a view, or you could be doing it from another partial view.
Either way, the code to render the partial needs to look like this:
<% Html.RenderPartial("LatestAnnouncements", announcements) %>
But - where do you get the announcements from.
Assuming you have a Repository/DAL/helper method to get the latest announcements - i think you should have the ViewModel's you require inheriting from a base ViewModel:
public class AnnouncementViewModelBase
{
protected IEnumerable<Announcement> GetAnnouncements()
{
// call DAL
}
}
Then any master/view/partial that needs to render the latest announcements partial should be bound to a ViewModel which inherits from that base view model.
In the cases where the master/view/partial is not strongly-typed (e.g dynamic view), you can stick it in the ViewData. But if you have organized your view's correctly this shouldn't be required.
Is this the kind of thing you're after? How to pass data from view to UserControl in ASP.NET MVC?
You should use RenderAction in this kind of scenario, so that you do not have bother to pass the required data in each action method of your controllers.
I think the best way would be to use #Html.Action. This would allow me to call my actions dedicated to my usercontrols data and I can call it from anywhere.

When would you not use a strongly-typed ASP.NET MVC view?

Assuming that an ASP.NET MVC View is going to show data, is there any scenario where you would not want to use a strongly-typed view?
Places where there is no model -- like Logon/Logoff.
I think that you should follow the practice of always using strongly typed views, unless no model isused at all like previously mentioned for pages like login.
I'm forced to put some data in layout. Cause I couldn't find any good way to make strongly typed layout, I'm passing necessary data through controller base class and picking it up at layout through indexer of viewData by key.
For partialviews i just nest form models, no problems there i guess.

How to add a codebehind to as asp.net mvc view?

I'm experiencing some craziness that I just can't figure out.
I've created the following class:
public abstract class AbstractView<T> : ViewPage<T> where T : class
which gives me some useful helpers and I'm using it in my views like this:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Project.Web.Mvc.AbstractView<Project.Domain.Entities.Example>" %>
This all works fine. Now I've got to make a view which needs lots of complex rendering code, so I want to give my view a codebehind, so I can put all this presentational logic in it.
However, when I do:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Project.Web.Views.Examples.View" CodeBehind="~/Views/Examples/View.aspx.cs" %>
public class View : Project.Web.Mvc.AbstractView<Project.Domain.Entities.Example>
Model is always null when I debug the view, which subsequently gives me:
"The view 'View' or its master could not be found. The following locations were searched..."
What's going on?
P.S. don't tell me codebehinds are evil. I'm writing presentation specific logic, and lots of it. It's not going inline in the aspx.
You could try using a code-alongside. By that I mean a class deriving from AbstractView<T> that is only used by this one view. It's virtually the same concept as a code-behind. Then just point at that instead of using AbstractView<T>.
Also, your Model won't be hooked up until OnLoad (could be earlier, I've never done it myself) so that could be your problem if you're trying to use it in the constructor.
Otherwise you might want to look at using a ViewModel so that instead of you passing what I assume are raw domain objects, you do the custom formatting in the ViewModel and pass that to AbstractView<T>.
Using View as your class name is probably not a good idea. Using something a more specific.
I take it you ae declaring the class in the namespace specified in the Inherits attribute?
Ok my bad, the model isnt ready in the codebehind until onload, and i was doing things in the constructor.
Strange that MVC would say "cant find the view" when it clearly can, there was just an exception thrown

Resources