⬆️ ⬇️

ASP.NET MVC Lesson 8. View, Razor, error page

The purpose of the lesson . Learn how to output data in html, using Razor. Helper. PageableData. Dynamic forms. RedirectToLogin, RedirectToNotFoundPage. Error page. RssActionResult.



The foundation


So, we will consider as part of View is arranged.

In the controller, all action methods return the type ActionResult. And to display the result, we use:

return View(modelData);





The main parameters of the View can be:





The choice of which View to use is as follows:



let's start the study.

')

Razor


When creating a View, there is a choice between two engines: ASPX and Razor. We will not use the first one in the future, so let's talk about Razor.







ASPX was a thundering engine with <% %> %% <% %> tags for code execution and <%: %> for data output.



Razor uses the @Model.Name . Those. everything that begins with @ translates into either the code execution mode, or the @foreach() {…} data output, or @if() { … } else { … } :



 @if (Model.Any()) { <p></p> } @foreach (var role in Model) { <div class="item"> <span class="id"> @role.ID </span> <span class="name"> @role.Name </span> <span class="Code"> @role.Code </span> </div> } 




There are tags inside {} - this is a marker of what the template is. For simple execution of code inside a template, use the @ {code} structure, for correct output of data inside attributes or with a text - (string result):

 @{ int i = 0; } @foreach (var role in Model) { <div class="item @(i % 2 == 0 ? "odd" : "")"> <span class="id"> @role.ID </span> <span class="name"> @role.Name </span> <span class="Code"> @role.Code </span> </div> i++; } 


To display non-tagged text, you need to use pseudo tags:

 @foreach (var role in Model) { @role.Name<text>, </text> } 


To output html text, either MvcHtmlString must be returned, or use the Html .Raw (html-string-value) construct, otherwise the text will be output with tag escaping.



Pageabledata


Consider paginated table output from the database. Let's analyze:

  1. The controller should get in the parameters the value of the page that we will display
  2. By default this will be the first page.
  3. When withdrawing, we need to know:

    1. List of database elements that are displayed
    2. Number of pages
    3. Current page




Create a Generic PageableData class (/Models/Info/PageableData.cs):

 public class PageableData<T> where T : class { protected static int ItemPerPageDefault = 20; public IEnumerable<T> List { get; set; } public int PageNo { get; set; } public int CountPage { get; set; } public int ItemPerPage { get; set; } public PageableData(IQueryable<T> queryableSet, int page, int itemPerPage = 0) { if (itemPerPage == 0) { itemPerPage = ItemPerPageDefault; } ItemPerPage = itemPerPage; PageNo = page; var count = queryableSet.Count(); CountPage = (int)decimal.Remainder(count, itemPerPage) == 0 ? count / itemPerPage : count / itemPerPage + 1; List = queryableSet.Skip((PageNo - 1) * itemPerPage).Take(itemPerPage); } } 




By default, the number of displayed values ​​on a page is 20, but we can change this parameter in the constructor. We transfer IQueryable and we calculate the number of CountPage pages. Using PageNo, select the page:

 List = queryableSet.Skip((PageNo - 1) * itemPerPage).Take(itemPerPage); 




In the controller we use:

 public class UserController : DefaultController { public ActionResult Index(int page = 1) { var data = new PageableData<User>(Repository.Users, page, 30); return View(data); } … 


In View we use this class:

 @model LessonProject.Models.Info.PageableData<LessonProject.Model.User> @{ ViewBag.Title = "Users"; Layout = "~/Areas/Default/Views/Shared/_Layout.cshtml"; } <h2>Users</h2> <p> @foreach (var user in Model.List) { <div class="item"> <span class="id"> @user.ID </span> <span class="email"> @user.Email </span> <span class="activateDate"> @user.AddedDate </span> </div> } </p> 


Run, check (http: // localhost / User)







To continue, we will generate more data (just ctrl-c, ctrl-v in the table in Server Explorer)







Let us turn to the creation of the Helper paginator, which will give us the opportunity to scroll through this list.



Helper (PagerHelper)


Since we use bootstrap, we will do paginator on the basis of it. In code, it looks like this:



 <div class="pagination"> <ul> <li><a href="#">Prev</a></li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> <li><a href="#">Next</a></li> </ul> </div> 




We are only interested in the inside.

Helper is created as an Extension for the System.Web.Mvc.HtmlHelper class. The plan is:



The code will look like this:

 public static MvcHtmlString PageLinks(this HtmlHelper html, int currentPage, int totalPages, Func<int, string> pageUrl) { StringBuilder builder = new StringBuilder(); //Prev var prevBuilder = new TagBuilder("a"); prevBuilder.InnerHtml = "«"; if (currentPage == 1) { prevBuilder.MergeAttribute("href", "#"); builder.AppendLine("<li class=\"active\">" + prevBuilder.ToString() + "</li>"); } else { prevBuilder.MergeAttribute("href", pageUrl.Invoke(currentPage - 1)); builder.AppendLine("<li>" + prevBuilder.ToString() + "</li>"); } //  for (int i = 1; i <= totalPages; i++) { //      if (((i <= 3) || (i > (totalPages - 3))) || ((i > (currentPage - 2)) && (i < (currentPage + 2)))) { var subBuilder = new TagBuilder("a"); subBuilder.InnerHtml = i.ToString(CultureInfo.InvariantCulture); if (i == currentPage) { subBuilder.MergeAttribute("href", "#"); builder.AppendLine("<li class=\"active\">" + subBuilder.ToString() + "</li>"); } else { subBuilder.MergeAttribute("href", pageUrl.Invoke(i)); builder.AppendLine("<li>" + subBuilder.ToString() + "</li>"); } } else if ((i == 4) && (currentPage > 5)) { //  builder.AppendLine("<li class=\"disabled\"> <a href=\"#\">...</a> </li>"); } else if ((i == (totalPages - 3)) && (currentPage < (totalPages - 4))) { //  builder.AppendLine("<li class=\"disabled\"> <a href=\"#\">...</a> </li>"); } } //Next var nextBuilder = new TagBuilder("a"); nextBuilder.InnerHtml = "»"; if (currentPage == totalPages) { nextBuilder.MergeAttribute("href", "#"); builder.AppendLine("<li class=\"active\">" + nextBuilder.ToString() + "</li>"); } else { nextBuilder.MergeAttribute("href", pageUrl.Invoke(currentPage + 1)); builder.AppendLine("<li>" + nextBuilder.ToString() + "</li>"); } return new MvcHtmlString("<ul>" + builder.ToString() + "</ul>"); } 




Add the namespace LessonProject.Helper to the ads in the View. This can be done in two ways:





Add a paginator in View:

  <div class="pagination"> @Html.PageLinks(Model.PageNo, Model.CountPage, x => Url.Action("Index", new {page = x})) </div> 




Pay attention to the design

x => Url.Action("Index", new {page = x})

This is the delegate that returns the link to the page. And Url.Action () - forms a link to the page / User / Index with the parameter page = x.

That's what happened (reduced the number of output per page to 5, so that more pages were formed):







SearchEngine


The next step to view the data will be to create a search. The search will be simple, by matching the substring in one of the data fields. The input parameter is searchString.

 public ActionResult Index(int page = 1, string searchString = null) { if (!string.IsNullOrWhiteSpace(searchString)) { //  return View(data); } else { var data = new PageableData<User>(Repository.Users, page, 5); return View(data); } } 




Create a SearchEngine class that accepts values.
  IQueryable,   ,      (/Global/SearchEngine.cs): 
    

, , [,], {,}, (,):

/// <summary> /// The regex strip html. /// </summary> private static readonly Regex RegexStripHtml = new Regex("<[^>]*>", RegexOptions.Compiled); private static string StripHtml(string html) { return string.IsNullOrWhiteSpace(html) ? string.Empty : RegexStripHtml.Replace(html, string.Empty).Trim(); } private static string CleanContent(string content, bool removeHtml) { if (removeHtml) { content = StripHtml(content); } content = content.Replace("\\", string.Empty). Replace("|", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty). Replace("[", string.Empty). Replace("]", string.Empty). Replace("*", string.Empty). Replace("?", string.Empty). Replace("}", string.Empty). Replace("{", string.Empty). Replace("^", string.Empty). Replace("+", string.Empty); var words = content.Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var sb = new StringBuilder(); foreach (var word in words.Select(t => t.ToLowerInvariant().Trim()).Where(word => word.Length > 1)) { sb.AppendFormat("{0} ", word); } return sb.ToString(); }




:

public static IEnumerable<User> Search(string searchString, IQueryable<User> source) { var term = CleanContent(searchString.ToLowerInvariant().Trim(), false); var terms = term.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var regex = string.Format(CultureInfo.InvariantCulture, "({0})", string.Join("|", terms)); foreach (var entry in source) { var rank = 0; if (!string.IsNullOrWhiteSpace(entry.Email)) { rank += Regex.Matches(entry.Email.ToLowerInvariant(), regex).Count; } if (rank > 0) { yield return entry; } } }



. regex . , Email .



:

, , «cher [2]», , «cher 2». regex = (cher|2). , IQueryable

, IEnumerable - yield return entry

IQueryable, , (/Global/SearchEngine.cs):

, , [,], {,}, (,):

/// <summary> /// The regex strip html. /// </summary> private static readonly Regex RegexStripHtml = new Regex("<[^>]*>", RegexOptions.Compiled); private static string StripHtml(string html) { return string.IsNullOrWhiteSpace(html) ? string.Empty : RegexStripHtml.Replace(html, string.Empty).Trim(); } private static string CleanContent(string content, bool removeHtml) { if (removeHtml) { content = StripHtml(content); } content = content.Replace("\\", string.Empty). Replace("|", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty). Replace("[", string.Empty). Replace("]", string.Empty). Replace("*", string.Empty). Replace("?", string.Empty). Replace("}", string.Empty). Replace("{", string.Empty). Replace("^", string.Empty). Replace("+", string.Empty); var words = content.Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var sb = new StringBuilder(); foreach (var word in words.Select(t => t.ToLowerInvariant().Trim()).Where(word => word.Length > 1)) { sb.AppendFormat("{0} ", word); } return sb.ToString(); }




:

public static IEnumerable<User> Search(string searchString, IQueryable<User> source) { var term = CleanContent(searchString.ToLowerInvariant().Trim(), false); var terms = term.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var regex = string.Format(CultureInfo.InvariantCulture, "({0})", string.Join("|", terms)); foreach (var entry in source) { var rank = 0; if (!string.IsNullOrWhiteSpace(entry.Email)) { rank += Regex.Matches(entry.Email.ToLowerInvariant(), regex).Count; } if (rank > 0) { yield return entry; } } }



. regex . , Email .



:

, , «cher [2]», , «cher 2». regex = (cher|2). , IQueryable

, IEnumerable - yield return entry

  IQueryable,   ,      (/Global/SearchEngine.cs): 
    

, , [,], {,}, (,):

/// <summary> /// The regex strip html. /// </summary> private static readonly Regex RegexStripHtml = new Regex("<[^>]*>", RegexOptions.Compiled); private static string StripHtml(string html) { return string.IsNullOrWhiteSpace(html) ? string.Empty : RegexStripHtml.Replace(html, string.Empty).Trim(); } private static string CleanContent(string content, bool removeHtml) { if (removeHtml) { content = StripHtml(content); } content = content.Replace("\\", string.Empty). Replace("|", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty). Replace("[", string.Empty). Replace("]", string.Empty). Replace("*", string.Empty). Replace("?", string.Empty). Replace("}", string.Empty). Replace("{", string.Empty). Replace("^", string.Empty). Replace("+", string.Empty); var words = content.Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var sb = new StringBuilder(); foreach (var word in words.Select(t => t.ToLowerInvariant().Trim()).Where(word => word.Length > 1)) { sb.AppendFormat("{0} ", word); } return sb.ToString(); }




:

public static IEnumerable<User> Search(string searchString, IQueryable<User> source) { var term = CleanContent(searchString.ToLowerInvariant().Trim(), false); var terms = term.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var regex = string.Format(CultureInfo.InvariantCulture, "({0})", string.Join("|", terms)); foreach (var entry in source) { var rank = 0; if (!string.IsNullOrWhiteSpace(entry.Email)) { rank += Regex.Matches(entry.Email.ToLowerInvariant(), regex).Count; } if (rank > 0) { yield return entry; } } }



. regex . , Email .



:

, , «cher [2]», , «cher 2». regex = (cher|2). , IQueryable

, IEnumerable - yield return entry

IQueryable, , (/Global/SearchEngine.cs):

, , [,], {,}, (,):

/// <summary> /// The regex strip html. /// </summary> private static readonly Regex RegexStripHtml = new Regex("<[^>]*>", RegexOptions.Compiled); private static string StripHtml(string html) { return string.IsNullOrWhiteSpace(html) ? string.Empty : RegexStripHtml.Replace(html, string.Empty).Trim(); } private static string CleanContent(string content, bool removeHtml) { if (removeHtml) { content = StripHtml(content); } content = content.Replace("\\", string.Empty). Replace("|", string.Empty). Replace("(", string.Empty). Replace(")", string.Empty). Replace("[", string.Empty). Replace("]", string.Empty). Replace("*", string.Empty). Replace("?", string.Empty). Replace("}", string.Empty). Replace("{", string.Empty). Replace("^", string.Empty). Replace("+", string.Empty); var words = content.Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var sb = new StringBuilder(); foreach (var word in words.Select(t => t.ToLowerInvariant().Trim()).Where(word => word.Length > 1)) { sb.AppendFormat("{0} ", word); } return sb.ToString(); }




:

public static IEnumerable<User> Search(string searchString, IQueryable<User> source) { var term = CleanContent(searchString.ToLowerInvariant().Trim(), false); var terms = term.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var regex = string.Format(CultureInfo.InvariantCulture, "({0})", string.Join("|", terms)); foreach (var entry in source) { var rank = 0; if (!string.IsNullOrWhiteSpace(entry.Email)) { rank += Regex.Matches(entry.Email.ToLowerInvariant(), regex).Count; } if (rank > 0) { yield return entry; } } }



. regex . , Email .



:

, , «cher [2]», , «cher 2». regex = (cher|2). , IQueryable

, IEnumerable - yield return entry

Source: https://habr.com/ru/post/176063/



All Articles