There are several series of tutorials on asp.net mvc online, so don't start from scratch, and recommend a few links at the end, so you can look at the system from scratch. 
 
 
1, asp.net mvc introduction and the difference with asp.net webform 
 
In order to find out asp.net mvc in the end is not worth it, over and over for more than a week, read a lot of information and comments, the final decision is worth a use. MVC is not a simple design pattern, more like an architectural model, or a thought, just beginning to listen to MVC is the template engine, nvelocity,stringtempleate, etc., but feel if only to use the template this independent foreground design method, There is no need to use ASP.net MVC, most of which can be done with Repeaterk controls and custom controls, and the ASPX page can write C # code, and some of the more complex interface representation logic can be realized with ordinary webform, in fact asp.net The View section of MVC defaults to the ASPX parser. The view section of ASP.net MVC allows you to write large, complex Web sites that are more convenient, low-level, and straightforward, and are popular with developers familiar with Css,js. 
 
When you understand the idea of MVC, you'll find that the benefits of ASP.net MVC are really controller and action, and you can write a piece of code that knows exactly what request is being processed, after all, the Web program is dealing with an HTTP request, unlike Windows desktop programs, More intuitive based on event-driven. asp.net MVC controller makes it easy to write web APIs or restful interfaces (which may have been done in HttpHandler), and these controller are only responsible for providing data (specific ActionResult classes, such as Jsonresult,javascriptresult, etc.) to the user, such as an Ajax call, or the view layer. 
 
As for the model layer, I see most of the Internet is implemented with LINQ to SQL, after all, it is very simple to use, design a table, with a LINQ designer to vs.net in the use of a drag. And in itself is strongly typed, and then add some partial methods on the automatically generated code, can realize the validity of the data validation and so on. There is a LINQ to do the model data persistence and query time more convenient, directly with DbContext a class, additions and deletions to check the almighty fix. 
 
There is a house, ASP.net mvc, while providing advanced ideas and some conveniences, But some of the things before ASP.net, such as some of the server controls that were previously written, can't be used, WebPart, skin, various data-bound controls, and so on, but master pages are still available, ASP.net Ajax Control Toolkit (service side) Can not be used, but ASP.net Ajax library (client JS libraries) can continue to use, based on the page and directory authorization is not available (because there is no page, only view), but membership and forms authentication is supported. The life cycle of the standard WebForm has changed, many events have gone, and now you can write interceptors (action interceptors, result interceptors, and exception interceptors) to influence the processing of requests, there are some differences, in short, the loss of things, there are flexible ways to find it back. 
 
 
2. How does LINQ to SQL get the value of the identity column produced by the INSERT statement?
 
In fact, it is very simple, the object inserted into the database, directly take the value of the line, the following bbspost is an entity class, where PostID in the database is the self-added column. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
var db = new Bbsdbcontext (CONNSTR); 
  
Bbspost post = new Bbspost () 
  
Post. Postuser = User.Identity.Name; 
  
Post. Posttime = DateTime.Now; 
  
Db. Bbsposts.insertonsubmit (POST); 
  
Db. SubmitChanges (); 
  
int PostID = post. PostID; The value of the identity column can be fetched here. 
  
 
 
 
  
 
3. How do I maintain the scroll bar position in asp.net mvc after the request is submitted?
 
In the WebForm is simpler, in the Web.config configuration maintainscrollpositiononpostback=true is done, but in MVC is not. We know the principle, we can do it ourselves, in fact, in the submission of the form or scroll bar scrolling events to capture the current scroll bar position, put the value in a hidden field, submitted to the server, the server answer, from the hidden field to remove the scroll bar position, using JS to manipulate the scroll bar to the last position. 
Let's first write a hidden field in the view, as follows 
<%= Html.hidden ("scroll", viewdata["Scrool"])%> 
Then, in the action that handles the client request, store the value submitted (from the FormCollection) in the ViewData. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
Public ActionResult reply (Bbspost post, FormCollection coll) { 
  
... 
  
viewdata["scroll"] = coll["scroll"]; 
  
... 
  
Return View ("Show_post", posts); 
  
} 
  
 
 
 
  
This will save the position of the scroll bar before submitting the page, and then we'll write some logic in jquery to achieve the final effect. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
<script type= "Text/javascript" > 
  
$ (function () { 
  
$ (document). Scroll (function () { 
  
Updates the position value of the scroll bar in the hidden field when the scroll bar is scrolled, and the test does not support IE8, Khan 
  
$ ("#scroll"). Val (Document.documentElement.scrollTop); 
  
}); 
  
$ ("form"). Submit (function () { 
  
Update the position value of the scroll bar in the hidden field when the form is submitted 
  
$ ("#scroll"). Val (Document.documentElement.scrollTop); 
  
return true; 
  
}); 
  
Remove the value of the hidden field in the Document.load event and set the scroll bar position 
  
Document.documentElement.scrollTop = $ ("#scroll"). Val (); 
  
}); 
  
 
  
</script> 
  
 
 
 
  
 
4. Verify user input 
 
Verification of data validation basically which program is not able to hide, LINQ and asp.net mvc, so that the implementation of data validation is also very convenient. 
The class that is automatically generated by the LINQ to SQL Designer is a partial class, which is half a block of classes, you can write a step-by-step class, add some extended methods to the auto-generated classes, and we add a Getruleviolations method to the LINQ entity class Bbspost. A IsValid property in which the Getruleviolations method verifies the validity of the value assigned to the entity class and returns an enumerator with the yield keyword, which can write your own data validation logic. 
The IsValid property calls the Getruleviolations method internally, which means that data validation does not pass if the returned enumerator's count is not 0. 
In addition to the way LINQ to SQL writes invalid data to the database, we add two lines of code to the OnValidate distribution method, throwing an exception before the database is written without data validation. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
Public partial class Bbspost { 
  
public bool IsValid { 
  
get {return (Getruleviolations ()). Count () = = 0); } 
  
} 
  
 
  
Public ienumerable<ruleviolation> getruleviolations () { 
  
if (String.IsNullOrEmpty (Title)) 
  
Yield return new Ruleviolation ("title must be entered", "title"); 
  
if (String.IsNullOrEmpty (Content)) 
  
Yield return new Ruleviolation ("contents must be entered", "content"); 
  
Yield break; 
  
} 
  
 
  
partial void OnValidate (Changeaction action) { 
  
if (! IsValid) 
  
throw new ApplicationException ("rule violations Prevent saving"); 
  
} 
  
} 
  
 
 
 
  
Ruleviolation is an auxiliary class, very simple. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
public class Ruleviolation { 
  
 
  
public string ErrorMessage {get; private set;} 
  
public string PropertyName {get; private set;} 
  
 
  
Public ruleviolation (String errormessage) { 
  
ErrorMessage = errormessage; 
  
} 
  
 
  
Public Ruleviolation (String errormessage, String propertyname) { 
  
ErrorMessage = errormessage; 
  
propertyname = PropertyName; 
  
} 
  
} 
  
 
 
 
  
When the action is written, the exception that captures the SubmitChanges action is captured, and then the exception that adds custom validation logic to the Modelstate, Modelstate passes the added exception to the view layer for use by the view layer. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
try { 
  
var db = new Bbsdbcontext (globalhelper.conn); 
  
Post. Postuser = User.Identity.Name; 
  
Other assignment operations 
  
Db. Bbsposts.insertonsubmit (POST); 
  
Db. SubmitChanges (); 
  
Modelstate.clear (); 
  
} 
  
catch (Exception ex) { 
  
Modelstate.addmodelerrors (post. Getruleviolations ()); 
  
Modelstate.addmodelerror ("Exception", ex); 
  
} 
  
The default modelstate has no Addmodelerrors method, only the Addmodelerror method, we have later added an extension method to him, as follows 
  
public static class Modelstatehelpers { 
  
public static void Addmodelerrors (this modelstatedictionary modelstate, ienumerable<ruleviolation> errors) { 
  
foreach (ruleviolation issue in errors) { 
  
Modelstate.addmodelerror (issue. PropertyName, issue. ErrorMessage); 
  
} 
  
} 
  
} 
  
 
 
 
  
The Html.validationmessage method is used in the view layer to output the error description at the appropriate location, and if there is a modelstate error in the view rendering, the corresponding error description is automatically displayed, as shown below. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
<p> 
  
<label for= "Title" > 
  
Title:</label> 
  
<%= Html.textbox ("Title", NULL, new {style = "width:700px;"}) %> 
  
<%= html.validationmessage ("Title")%> 
  
</p> 
  
<p> 
  
<label for= "Content" > 
  
Content:</label> 
  
<%= Html.textarea ("Content", NULL, new {style = "width:700px;height:100px;"}) %> 
  
<%= html.validationmessage ("Content")%> 
  
</p> 
  
 
 
 
  
 
5, LINGQ to SQL paging 
 
SQL Server 2005 has a very strong paging function, LINQ to SQL has good support,iqueryable<t> the Skip and take methods are ultimately the raw page of SQL, write a helper class (taken from Nerddinner), The attribute of this class is very simple, see name know meaning, do not introduce. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
public class Paginatedlist<t>: list<t> { 
  
 
  
public int PageIndex {get; private set;} 
  
public int PageSize {get; private set;} 
  
public int TotalCount {get; private set;} 
  
public int TotalPages {get; private set;} 
  
 
  
Public Paginatedlist (iqueryable<t> source, int pageIndex, int pageSize) { 
  
PageIndex = PageIndex; 
  
PageSize = PageSize; 
  
TotalCount = source. Count (); 
  
TotalPages = (int) math.ceiling (TotalCount/double) PageSize); 
  
 
  
This. AddRange (source. Skip (PageIndex * PageSize). Take (PageSize)); This will stop the delay loading and load the data into memory. 
  
} 
  
 
  
public bool Haspreviouspage { 
  
get { 
  
Return (PageIndex > 0); 
  
} 
  
} 
  
 
  
public bool Hasnextpage { 
  
get { 
  
Return (Pageindex+1 < totalpages); 
  
} 
  
} 
  
} 
  
 
 
 
  
It is very simple to use, after you get a IQueryable with LINQ to SQL, and then use the new one paginatedlist to represent a paginated dataset. 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
var posts = from post in db. Bbsposts 
  
Where post. CategoryID = = ID && post. ParentID = 0 
  
by post. PostID Descending 
  
Select Post; 
  
const int pageSize = 10; 
  
var pageposts = new Paginatedlist<bbspost> (posts, page?? 0, PageSize); 
  
Return View (pageposts); 
  
 
 
 
  
Posts is a Iqueryable<bbspost> object generated with LINQ to SQL, at which point the SQL statement is not executed, delays execution, and then the new one paginatedlist<bbspost> The resulting SQL statements will be modified, and finally the pageposts passed to the view layer to use the line, the view layer we use a strong type of view, as follows 
<%@ Page title= "" Language= "C #" masterpagefile= "~/views/shared/site.master" 
inherits= "System.web.mvc.viewpage<simplebbs.helpers.paginatedlist<simplebbs.models.bbspost>>"%> 
The page to display the previous page, the next page of the link, it is very simple to write 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
<div class= "Pagination" > 
  
<% if (model.haspreviouspage) {%> 
  
<%= html.routelink ("prev", 
  
"Default", 
  
New {page= (model.pageindex-1)})%> 
  
<%}%> 
  
<% if (model.hasnextpage) {%> 
  
<%= html.routelink ("next page"), 
  
"Default", 
  
New {page = (Model.pageindex + 1)})%> 
  
<%}%> 
  
</div> 
  
 
 
 
  
 
6. View the SQL statements generated by LINQ to SQL?
 
Some people suspect that LINQ to SQL has a performance problem think that it generated statements are not reliable, in fact, it generated statements are parameterized queries, the general based on the primary key or indexed columns of queries and most of the update operation performance should not be worse than the handwriting of SQL, if not at ease, you can take LINQ to SQL generated SQL is printed out to avoid the performance look-up statement generated. 
The following code 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
var db = new Bbsdbcontext (conn); 
  
var posts = from post in db. Bbsposts 
  
Where post. CategoryID = = 1 && post. ParentID = 0 
  
by post. PostID Descending 
  
Select New {post. PostID, Post. Title, Post. Content}; 
  
Db. Log = Response.Output; To track automatically generated SQL statements 
  
Rpt1. DataSource = posts; 
  
Rpt1. DataBind (); The SQL query executes only if the statement that uses the data is actually executed, before which the statement is only a statement that is automatically deferred. 
  
 
 
 
  
A LINQ to SQL generated SQL statement is seen on the page 
SELECT [T0]. [PostID], [t0]. [Title], [t0]. [Content] from [dbo]. [Bbs_post] As [t0] WHERE ([t0].[ CategoryID] = @p0) and ([t0].[ ParentID] = @p1) Order by [T0]. [PostID] DESC--@p0: Input Int (Size = 0; Prec = 0; Scale = 0 [1]--@p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0]--context:sqlprovider (Sql2005) Model:attributedmetamodel build:3.5.30729.1 
If you change to the following paging method 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
var db = new Bbsdbcontext (conn); 
  
var posts = from post in db. Bbsposts 
  
Where post. CategoryID = = 1 && post. ParentID = 0 
  
by post. PostID Descending 
  
Select Post; 
  
Db. Log = Response.Output; 
  
Rpt1. DataSource = posts. Skip (1 * 5). Take (5); 
  
Rpt1. DataBind (); 
  
 
 
 
  
Will output the following SQL 
SELECT [T1]. [CategoryID], [T1]. [PostID], [T1]. [ParentID], [T1]. [Title], [T1]. [Content], [T1]. [Postuser], [T1]. [Posttime] From (SELECT row_number () over (t0].[ PostID] DESC) as [Row_number], [t0]. [CategoryID], [T0]. [PostID], [t0]. [ParentID], [t0]. [Title], [t0]. [Content], [t0]. [Postuser], [t0]. [Posttime] from [dbo]. [Bbs_post] As [t0] WHERE ([t0].[ CategoryID] = @p0) and ([t0].[ ParentID] = @p1)) as [T1] WHERE [T1]. [Row_number] BETWEEN @p2 + 1 and @p2 + @p3 ORDER BY [T1]. [Row_number]--@p0: Input Int (Size = 0; Prec = 0; Scale = 0 [1]--@p1: Input Int (Size = 0; Prec = 0; Scale = 0 [0]--@p2: Input Int (Size = 0; Prec = 0; Scale = 0 [5]--@p3: Input Int (Size = 0; Prec = 0; Scale = 0) [5]--Context:sqlprovider (Sql2005) Model:attributedmetamodel build:3.5.30729.1 
You can see that these queries are all parameterized queries, not SQL, and you use the Row_number function, LINQ to SQL is more familiar with SQL Server. 
 
 
7, to set an action requires identity authentication?  
 
Because the page-based authorization is not available, we have to authorize an action, such as the need to log in to reply to the post, and then add the attribute modification that requires authentication on the reply action, as follows 
[Acceptverbs (Httpverbs.post), authorize] 
? public ActionResult Reply (Bbspost post, FormCollection coll) { 
This approach is implemented in AOP injection mode, more interceptor examples, or want to write their own interceptors to Google some information to see. 
 
 
8, how the user submitted form data into a strong type.  
 
We all know that the data submitted on the Web page includes form and QueryString, which are all string types out of the server, and we need a single processing parameter in the ASP era, which is handy in asp.net mvc, like you have a bbspost class, There are title and content and CategoryID 3 attributes, and there are two text boxes on the form, title and content, and an CategoryID in the Address bar argument, you can take a bbspost class directly in the action, And the attributes are filled for you, do not need you to take out a string and then new a Bbspost class, and then the type assignment, such as a series of operations, as follows 
Public ActionResult reply (Bbspost post, FormCollection coll) {} 
The first parameter is automatically populated with a strong type, and the second parameter can take out the data submitted by the original form. If you want to learn more about the binding of form data and strongly typed data, look for details about how Defaultmodelbinder works. 
 
 
9, to HtmlHelper plus extension methods.  
 
One of the best practices in asp.net mvc is to add some common extension methods to the view layer for easy use, not to write help classes everywhere, such as formatting posts into HTML when displaying posts, and we've written the following extension methods 
 
 
  
  Copy Code code as follows: 
 
 
  
 
  
  
public static class Htmlhelperextension { 
  
public static string text2html (this htmlhelper helper, string input) { 
  
input = input. Replace ("", ""); 
  
input = input. Replace ("\ r \ n", "<br/>"); 
  
input = input. Replace ("T", ""); 
  
return input; 
  
} 
  
} 
  
 
 
 
  
To refer to the namespace in which the extension method resides first 
<%@ Import namespace= "Simplebbs.helpers"%> 
The extension method can then be used, as follows 
<%= html.text2html (Html.encode (item). Content))%> 
 
 
10, how to locate the script and CSS location 
 
If we have a particular level of directory, put the script, style sheets, etc. placed in a fixed directory, access to these resource paths in specific subdirectories may be inconsistent, in the WebForm only the server-side control to use the ~ syntax, whether deployed in the site root directory or virtual directory, ~ can represent the root directory of the application, We can use url.content in asp.net mvc, as follows 
<script src= "<%=url.content (" ~/scripts/jquery-1.3.2.min.js ")%>" type= "Text/javascript" ></script " >