1. Introduction
2. Create and run new app (with template)
3. Create and run new empty app
4. View
- Frame (master file)
- Inner content
5. Controller
- Empty app - summary
6. Model
7. Configuration
8. Deployment
9. Application object
10. Navigation among pages
- Link pointing out of project
11. Routing
12. Routing attributes MVC 5
13. Bundles
14. Rendering
- Section
- Partial view
15. Passing arguments
16. Session
17. Cookies
18. Authentication
19. Working with collections (displaying list)
20. Forms
- Associating style with controls
21. Display a file (like PDF)
22. Debugging remote requests
1. Introduction
You can find comprehensive information on the asp.net site.
MVC stands for Model-View-Controller
View: provides output visible in browser Controller: processes incoming request Model: container for data being presentedThis page describes ASP MVC 2 and shows differences in version 4.
2. Create and run new app (with template)
1. In Visual Studio (2010): Create New project, Web folder, ASP MVC 2 application, Folder for solution-Yes (helps to organize web site and test project under one folder), Create test project - Yes 2. F5 - Build and Run (opens in IE test instance) 3. If you put a break point to HomeController class, Index method, Visual Studio will stop there.If you want to explore project creating by ASP MVC 2 template, continue here: MSDN - First ASP MVC 2 App
If you want to follow fundamentals step by step, continue below:
3. Create and run new empty app
4. View
Frame (master file)
ASP <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title> </head> <body> <h1>My MVC Application</h1> <asp:ContentPlaceHolder ID="MainContent" runat="server" /> </body> </html>asp:ContentPlaceHolder will present content of the inner page. The entry page, known as Home page, is usually named and located as /Views/Home/Index.aspx
Inner content
ASP <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> My Home Page </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> Hello </asp:Content>
MasterPageFile has to refer to the location of the master file asp:Content with ContentPlaceHolderID TitleContent is referenced as master page title asp:Content with ContentPlaceHolderID MainContent is referenced as master page content
5. Controller
C# new { controller = "Home", action = "Index", id = UrlParameter.Optional }Controllers need to be placed under Controllers folder and file named like HomeController.cs
C# using System.Web.Mvc; public class HomeController : Controller { public ActionResult Index() { return View(); // returned View will be ~/Home/Index.aspx } }Now you can run the application and you see web site with text Hello. So far we achieved what we could achieve with simple static HTML page. When we need to pass some generated data to the view then we can leverage ASP MVC. Add the line below into Index() method of the HomeController
C# ViewData["MyText"] = "from HomeController";and extend asp:Content element with ContentPlaceHolderID="MainContent" as below
ASP <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> Hello <%: ViewData["MyText"]%> </asp:Content>If you run it now, you will see "Hello from HomeController" in your browser. In MVC 4, you can use ViewBag Assign the value in the controller
C# ViewBag.MyMessage="hello";and read it in the view
CSHTML @ViewBag.MyMessage
Empty app - summary
Add Views/Shared/Site.Master - xHTML site that hosts any site, e.g. Index.aspx as ContentControl Add Views/Home/Index.aspx - embedded content Add Controllers/HomeController.cs - controller for views under Views/Home global.asax.cs - created by Visual Studio
6. Model
C# public class MyModel { public string MyMessage { get; set; } }In the controller, create new instance of MyModel class, set the property and pass to the view
C# public ActionResult Index() { var model = new MyModel(); model.MyMessage = "hello model"; return View(model); }You need to update the view:
1. tell the view page about the type of the model in the inherits section, "AspMvcDemo1.Models.MyModel"
2. use any model class property - intellisense works here, but if you make a typo, compiler will not catch it!
ASP <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<AspMvcDemo1.Models.MyModel>" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> MyMessage: <%: Model.MyMessage %> </asp:Content>MVC 4 approach in .cshtml
CSHTML @model AspMvcDemo1.Models.MyModel ... MyMessage: @Model.MyMessage
7. Configuration
XML <appSettings> <add key="mykey" value="myValue" /> <appSettings>retrieve the value in the code as
C#
// in System.Configuration.dll
string myValue = System.Configuration.ConfigurationManager.AppSettings["myKey"];
8. Deployment
Start VS as admin
Right click on the project, Publish
Deployment type: Web deployment (copies files)
Profile: New profile, select name
Server: localhost
Site name: Default Web Site/MyApp
Open IIS (intemgr)
Righ click on MyApp folder and seletc "Convert to application"
Righ click on MyApp folder and select Manage Application\Advanced properties, set Application pool to ASP.net 4.0 (with Integrated pipeline mode) (if you use .net 4)
If the app uses an SQL DB, it may need its own app pool with identity set to the account that has access to the DB (or configure the DB to provide access to the account under which IIS runs)
9. Application object
More info: http://sandblogaspnet.blogspot.ch
ASP public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { } protected void Application_End() { } // Application_BeginRequest // Application_EndRequest // Application_AuthenticateRequest void Application_Error(object sender, EventArgs e) { Exception exc = Server.GetLastError(); ... Server.ClearError(); } void Session_Start(object sender, EventArgs e) { } void Session_End(object sender, EventArgs e) { } }
10. Navigation among pages
ASP <%: Html.ActionLink("TextVisibleToUser", "NameofMethodInController", "ControllerName", new { @myParamName = "abc" } )%>
Link pointing out of project
CSHTML @Html.Raw("<a href=\"" + Model.Link + "\">Go here</a>")
11. Routing
C# public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute( "Default", // Route name - has to be unique "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // defaults if URL does not contain all sections, e.g. /Home will use /Home/Index ); }
12. Routing attributes MVC 5
C# public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAttributeRoutes(); // you can still use classic definition here } ... public class PersonsController : Controller { // /people will handled by PersonsController [Route("people")] public ActionResult View(string id) {...} }
C# [RoutePrefix("people")] // prefix for all actions [Route("{action=index}")] // default route public class PersonsController : Controller { // /people/id [Route("Id"), name="personById"] // named route public PersonActionResult View(string id) {...} } .. // named route <a href="@Url.RouteUrl("personById")">Person by id</a>
13. Bundles
BundleConfig.cs is created by Visaul Studio under App_Start folder
C# public class BundleConfig { // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 public static void RegisterBundles(BundleCollection bundles) { bundles.Add(new StyleBundle("~/Content/css").Include( "~/Content/bootstrap.css", "~/Content/Site.css" )); bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js")); } }Defined bundles can be rendered e.g. in Views/Shared/_Layout.cshtml
CSHTML <html> <head> ... @Styles.Render("~/Content/css") </head> <body> ... @Scripts.Render("~/bundles/jquery") </body> </code>
14. Rendering
Section
web page Template is stored in shared/_layout.cshtml
CSHTML <html> <body> @RenderBody(); // includes view content that is not included in section(s) @IsSectionDefined("mySection") { @RenderSection("mySection"); // includes specific section } else { ... } @RenderSection("mySection", required:false); // skips if section does not exist <body> <html>page details are in myview.cshtml that gets embedded into _layout.cshtml
CSHTML @section mySection { a html content }Section can be used to wrap JavaScript into sections and render them at the end of the template.
Partial view
CSHTML <html> <body> @Html.Partial("CompanyName"); // includes HTML from myPartialView <body> <html>CompanyName.cshtml
CSHTML <h1>Company One</h1> @ ... another code
15. Passing arguments
C# string myArgValue = Request.QueryString["personId"]; // myArgValue = 1
16. Session
C# this.Session["userId"] = 123;What can cause session be terminated:
Ternination of all sessions
App pool unexpectedly recycled
SessionState Performance - Myth
17. Cookies
Write cookie inside the controller processing the request after user clicks the Login button
C# public class LoginController : Controller { public ActionResult Login(string userName, string password) { this.Response.Cookies.Add(new System.Web.HttpCookie("userName", userName)); } }Read cookie when login page gets loaded
C# public class LoginController : Controller { public ActionResult Index() { HttpCookie cookie = this.Request.Cookies["userName"]; if (cookie != null) { ViewBag.UserName = cookie.Value; } else { ViewBag.UserName = string.Empty; } } }
18. Authentication
CMD <system.web> <authentication mode="Windows" /> </system.web>
C# // inside controller (or view) string userName = this.Request.LogonUserIdentity.Name; // alternatively you can use shortcut string userName = this.User.Identity.Name;
19. Working with collections (displaying list)
C# public ActionResult Index() { List<Person> people = new List<Person>(); people.Add(new Person() { Name = "Paul", Height=178 }); people.Add(new Person() { Name = "George", Height=182 }); return View(people); }You need to update the view to describe type that will hold the collection as List<"AspMvc2Empty.Models.Person">
ASP <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<AspMvc2Empty.Models.Person>>" %> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <table> <% foreach (var item in Model) {%> <tr> <td> <%: item.Name %> </td> <td> <%: item.Height %> </td> </tr> <% } %> </table> </asp:Content>or in MVC 4 with Razor syntax
CSHTML @model List<AspMvcBasics.Models.Person> @{ ViewBag.Title = "People"; } <table> @foreach (var item in Model) { <tr> <td> @item.Name </td> <td> @item.Height </td> </tr> } </table>
20. Forms
If the form contain a ListBox, it necessary to pass data to feed the ListBox
C# public class LoginController : Controller { public ActionResult PrepareLogin() { // data for list box SelectList selection = new SelectList( new[] { new { Value = "A", Text = "Team A" }, new { Value = "B", Text = "Team B" }, new { Value = "C", Text = "Team C" }, }, "Value", "Text" ); return View(selection); } }Code in the view could look like below
CSHTML @model SelectList @using (Html.BeginForm("HandleLogin", "Login")) { User name: @Html.TextBox("userName", "JohnFirst") Password: @Html.Password("password") Remember me: @Html.CheckBox("rememberUserName", false) @Html.RadioButton("server", "s1", true) @:Server 1 @Html.RadioButton("server", "s2", false ) @:Server 2 @Html.ListBox("team", Model, new { size = 20 } ) <input type="submit" value="Login" /> }Note: when RadioButton is inside a container (div, td) then @: must be ommited
Wenn uses clicks "Login", the action called will the Index method in HomeController and values from input elements will be passed as arguments.
C# public class LoginController : Controller { public ActionResult HandleLogin(string userName, string password, string rememberUserName, string server, string team) { .... return View(); } }
Associating style with controls
C# @Html.TextBox("userName", (string)ViewBag.UserName, new { @class = "k-textbox" } )
21. Display a file (like PDF)
C# public FilePathResult Report() { return new FilePathResult(@"c:\myfolder\myfile.pdf", "application/pdf"); } // The FileContentResult approach enables file deletion in case the file was generated public FileContentResult Report() { byte[] content = System.IO.File.ReadAllBytes(@"c:\myfolder\myfile.pdf"); System.IO.File.Delete(@"c:\myfolder\myfile.pdf"); return new FileContentResult(content, "application/pdf"); }
22. Debugging remote requests
This is a Dev server that is sometimes called as Cassini and it does not accept requests from remote machines.
In order to be able to debug request coming from remote machines, you can install Fiddler and setup it as a proxy
on the machine where you have Visual Studio.
- In Fiddler, Tools > Fiddler Options, tab Connections, ensure that Allow remote clients to connect is set
- Close Fiddler
- Create a new HKEYCURRENTUSER\SOFTWARE\Microsoft\Fiddler2\ReverseProxyForPort of type DWORD and set the its decimal value to the port that you see in Internet Explorer that was opened by Visual Studio when you started debugging (usually above 30000, e.g. ).
- Start Fiddler.
- Start debugging your application
- In a browser (local or remote machine), go to http://{computer name}:{port above 30000}/{SpecificPage}
- If you set a breakpoint inside a web service method in Visual Studio, Visual Studio will stop the request execution there