This question might sound weird but I am finding it really difficult to digest a typical aspx page in ASP.NET MVC application. For example:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="aboutTitle" ContentPlaceHolderID="TitleContent" runat="server">
About Us
</asp:Content>
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>About</h2>
<p>
<% var cookie = Request.Cookies["mvcData"];
string lastRefreshValue = cookie == null? "Unknown": cookie["lastRefresh"];
%>
<%= Html.Encode ("Last Refreshed: " + lastRefreshValue) %>
<% var newCookie = new HttpCookie ("mvcData");
newCookie["lastRefresh"] = DateTime.Now.ToString ();
newCookie.Expires = DateTime.Now.AddSeconds (10);
Response.Cookies.Add (newCookie);
%>
<%= Html.Encode (ViewState["hello"] ?? "") %>
</p>
</asp:Content>
The code written in <% ... %> works well and as expected but how can I visualize this code in a class? Certainly it is inherited from ViewPage which is a class so whatever code written in <%..%> does get executed from some method. Right?
EDIT: The code written in <%..%> is NOT relevant. I wrote it to test cookies. The point is that how this code maps in a class?
-
All the code you have on your page could go in the controller class. What is basically happening is that your controller gets a model object that it passes to the view. You can either create this on the fly or use the ASP.Net MVC models folder to hold your model class. The controller should be dealing with any arguments you want to filter the model with, and pasing back a simple object to your view. This way you just have some string in the model class which can be put in a simple block like this
<%= myModelStringProperty %>
The view does inherit ViewPage, but you don't want to think of it as a class in it's own right. You should be programming against you model, and passing this to a view. Visual Studio will offer to strongly type your view to a particular model, so that you can use
<%= Model.MyProperty %>
To output the data where it is required. Just think of the view itself as an html template for your data.
Hemant : woa! I thought it inherits from ViewPage so it must be a **class** somehow in its own regard. How can this code be a part of controller class? Please can you elaborate?Mark Dickinson : Say you have a controller class with an ActionResult called MyPage. In this action set ViewData["MyKey"] = "Hi Hemant". Then make a view called MyPage and have this in it <%= ViewData["MyKey"] %>. -
When you create an ASP.Net MVC View(Page) it inherits from a class, as you said called ViewPage - which in return inherits from the Page class from ASP.Net WebForms (System.Web.UI.Page) and implements the IViewDataContainer interface (from MVC).
The Page class implements the IHttpHandler interface which IIS "talks" to.
All in all the IHttpHandler has a method called ProcessRequest which takes in a HttpContext instance.
A whole lot of magic happens around here (ok, it's not magic, but you get the idea) - the class is new'd up (your ViewPage) and it has several methods that gets invoked - some hook up the master pages and so forth and one of them will somehow read the .aspx page and have all normal output being wrapped in calls to Response.Write and the rest will be run as C# code (and <%= ... %> will be turned into Response.Write calls too) - and I do believe this parsing is done through Regular Expressions.
Please note, I am not expert on this and most likely technically wrong (and hey, someone feel free to post a better response to this, I tried to give the general understanding) but it should give the overall and general understanding of this.
EDIT: Also may I add that when you return a ViewResult through your Controller class it will eventually have a method invoked (I believe it is called Execute) that comes from the ActionResult class that it inherits from, which will then start a process of picking the right ViewEngine, the default one being the WebForms one, which then calls into the entire process stated above all this big gigantic edit mess.
@Hermant's comment As I said, if you take out the master pages stuff you need to think of the entire .aspx page being a method where all the stuff that is not wrapped in <% and %> to be C# code that looks like:
Response.Write("<html> ... <head> ...");
Every once in a while you have your <% ... %> calls which executes in between all these Response.Write calls.
Which say take the following .aspx
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %> <html> <head> <title><%= MyMethodCallToFindTitle() %></title> </head> <body> <ul> <% for(int i = 0; i < 10; i++){ %> <li><%= i %></li> <% } %> </ul> </body> </html>
It will somewhat be translated into a method looking "somewhat" like this:
Response.Write(@"<html> <head> <title>"); Response.Write(MyMethodCallToFindTitle()); Response.Write(@"</title> </head> <body> <ul>"); for(int i = 0; i < 10; i++){ Response.Write(@"<li>"); Response.Write(i); Response.Write(@"</li>"); } Response.Write(@"</ul> </body> </html>");
Note: of course there's a whole lot of stuff going on in case you had " hanging around in your HTML, along with newlines, tab-indentation and so forth, but this is the general overview.
I hope this helps.
Hemant : Just confused about code like <% int i = 0; %> which has no effect on HTML output! Whats interesting is that if i repeat the same block again, I get the error: A local variable named 'i' is already defined in this scope! Perhaps all the code is wrapped up in same method sequentially...kastermester : Yes it does - you need to think of your .aspx page as one big method.Mark Dickinson : @Kastermester - I'm not so sure about this. The view should not be doing any work ideally. Even loops and conditional parts should be handled with Partials, or helper methods. It is not really good to get anything but the most trivial code in your view. There are lots of other posts about this :)kastermester : @Mark Dickinson - he's not asking for pattern advice but rather how this "works" - it's the internals that's in focus here, now how you should construct this (at least this is how i understand this, based on Hermants comment in his question "The code written in <%..%> is NOT relevant. I wrote it to test cookies. The point is that how this code maps in a class?") -
You seem to be looking at this through a Webforms perspective - something MVC is not! While your code works, MVC is largely about separation of concerns: Your Controller should contain the logic/code of working with these cookies, while the View is responsible only for rendering the page (along with any ViewData the Controller passed to it).
Mark just pointed this out, but to use your code example you'd have something like this in your Controller:
public ActionResult About() { var cookie = Request.Cookies["mvcData"]; //rest of cookie code here Response.Cookies.Add(newCookie); ViewData["hello"] = "hi there..."; //add something to viewdata return View(); }
And within the view, you could render the message with <%=ViewData["hello"]%>. The cookie code is best kept in the Controller and not the view.
Hemant : I get your point about where code should go but my question was about whatever little code in view page is there, how it gets executed?
0 comments:
Post a Comment