当前位置:网站首页 / .NET CORE / 正文

ay的C#8.0和net5高级编程笔记16-使用MVC模式构建网站

时间:2021年05月08日 | 作者 : aaronyang | 分类 : .NET CORE | 浏览: 244次 | 评论 0

ASP.NET Core MVC构建网站

启动配置,身份验证,授权,路由,模型,视图和控制器等


ASP.NET Core Razor Pages适合简单网站。更复杂的可以使用MVC;

这里假设你以前已经弄过非NET Core版本的ASP.NET MVC了

vscode通过dotnet new mvc --auth Individual,这个新建一个MVC网站项目,将认证信息存储在SQLite数据库。dotnet new mvc --help查看更多mvc指令帮助信息

AY使用vs2019新建

image.png

image.png

image.png

运行默认项目后

image.png





单击注册

image.png

默认DOI模式,注册以后,发送邮件,访问者点击邮件的链接 才剋以注册成功。


image.png

没有数据库,你可以单击Apply Migrations,生成默认数据库。

MVC项目模板的一些内置功能使得网站更容易符合现代隐私要求,如欧盟通用数据保护条例(GDPR(2018年5月生效))链接:https://docs.microsoft.com/zh-cn/aspnet/core/security/gdpr


我本地装了sqlserver数据库,所以我修改了配置。

打开appsettings.json,默认数据库链接

"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-NorthwindMvc-7E54C335-B9C5-4F9C-B4EE-5E0113D704A0;Trusted_Connection=True;MultipleActiveResultSets=true"

修改为

"DefaultConnection": "Server=.;Database=aspnet-NorthwindMvc-7E54C335-B9C5-4F9C-B4EE-5E0113D704A0;Trusted_Connection=True;MultipleActiveResultSets=true"


重新注册,然后单击Apply Migrations,生成默认数据库

image.png

成功了,然后刷新页面


我们还没有配置电子邮件提供程序以发送电子邮件,下面我们模拟这个操作。

image.png

单击

image.png

单击了过后

image.png

单击Login

image.png


image.png

个人中心

image.png

审查ASP.NET Core MVC网站

image.png

Areas: 包含了ASP.NET Core Identity等身份验证功能所需的文件。

bin和obj:包含项目的已编译程序集

Controllers:C#类,有些方法,称作操作,用来获取模型并将它们传递给视图,例如HomeController.cs。

Data: 这个文件夹包含ASP.NET Core Identity使用Entity Framework Core迁移类,它们用来为身份验证和授权提供数据存储,例如ApplicationDbContext.cs。

Models:C#类,它们表示由控制器收集并传递给视图的所有数据。

Properties:包含用于IIS的launchSettings.json配置文件,可在开发期间启动网站。

Views:包含cshtml文件,和C#代码结合在一起动态生成HTML响应。_ViewStart文件用于设置默认布局,_ViewImports文件用于导入所有视图中使用的公共名称空间,如标记助手。

    Home:这个子文件夹包含用于主页和私有页面的Razor文件。

    Shared:包含共享布局的Razor文件、错误页面以及一些用于登录、接受隐私策略和管理cookie的分部视图。

wwwroot:包含网站中使用的静态内容,如CSS,图像,javascript和favicon.ico

app.db:用于存储已注册访客的SQLite数据库。

appsetting.json : 设置文件,例如用于ASP.NET Core Identity和日志级别的数据库链接字符串。

Program.cs:网站启动Main入口点,还有启动配置。

Startup.cs: 这个用于添加和配置网站需要的服务(例如ASP.NET Core Identity用于身份验证、SQLite用于数据存储等等)以及应用程序的路由。

更多配置:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/web-host?view=aspnetcore-5.0



回顾ASP.NET Core Identity数据库

image.png


打开Startup.cs文件

   public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDatabaseDeveloperPageExceptionFilter();


            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddControllersWithViews();

            //ay -- 这里我们添加
            services.AddRazorPages();
        }

虽然这篇文章,我们不会创建任何Razor页面,但是需要保留用于添加Razor Pages支持的方法调用。因为MVC网站使用ASP.NET Core Identity用于身份验证和授权,并且用户界面组件使用了Razor类库。

https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/scaffold-identity?tabs=netcore-cli


对AddDbContext方法的调用事注册依赖项服务的典型示例。ASP.NET Core实现了DI,这些控制器就可以通过构造函数请求所需的服务。开发人员可以在ConfigureServices方法中注册这些服务。

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0


关于配置中间件的更多信息:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-5.0


MapControllerRoute


image.png

路由模板,怎么把用户的 uri地址 找到对应的 操作上,还有传参啥的。

id后面的问号,表示id可有可无

controller=home

如果用户没有传入名称,则使用 等于号右侧的默认值

路由机制,这里不讲了,假设你已经会了,至少AY已经会的。



在Controller中

image.png

IActionResult返回,和ASP.NET MVC的ActionResult一样的。

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NorthwindMvc.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace NorthwindMvc.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

controller是可以单元测试的, https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/testing?view=aspnetcore-5.0


过滤器

动作级:可通过使用特性装饰的方法实现。只会影响控制器的一个方法。

控制器级别:影响控制器所有方法

全局级:在Startup类的ConfigureServices方法中,可将特性类的一个实例添加到IServiceCollection的Filters集合中,这将影响所有控制器的所有方法。


如果希望确保控制器的某个特定方法只能由某些安全角色的成员调用,就可以使用 [Authorize]特性装饰方法。

        [Microsoft.AspNetCore.Authorization.Authorize("Sales,Marketing")]
        public IActionResult SalesAndMarketEmployeesOnly()
        {
            return View();
        }

更多授权信息:https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/introduction?view=aspnetcore-5.0


使用筛选器缓存响应

image.png

上方ResponseCache

Duration: 秒为单位设置max-age HTTP响应头

Location: Any,Client或者None,用于设置cache-control HTTP响应头

NoStore:如果true,就忽略Duration和Location参数,并把cache-control HTTP响应头设置为no-store

响应缓存的更多信息:https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/response?view=aspnetcore-5.0


使用Route自定义路由

image.png

这样通过 private这个名字 ,就代替了 Privacy这个名字了



现在我们简单实践下

添加上一篇博客的 EF实体模型库

image.png

NorthwindMvc客户端添加引用

然后拷贝Northwind.db文件到项目根目录,设置输出到目录

由于这个项目使用sqlite,所以我们需要在Startup.cs的ConfigureServices添加代码


在Models文件内添加HomeIndexViewModel.cs类

using NorthwindEntitesLib;
using System.Collections.Generic;

namespace NorthwindMvc.Models
{
    public class HomeIndexViewModel
    {
        /// <summary>
        /// 访问人数
        /// </summary>
        public int VisitorCount { get; set; }
        /// <summary>
        /// 类别列表
        /// </summary>
        public IList<Category> Categories { get; set; }
        /// <summary>
        /// 产品列表
        /// </summary>
        public IList<Product> Products { get; set; }
    }
    
}

在HomeController.cs添加Northwind的引用

然后修改Index方法

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NorthwindContextLib;
using NorthwindMvc.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace NorthwindMvc.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        private Northwind db;
        public HomeController(ILogger<HomeController> logger, Northwind injectedContext)
        {
            _logger = logger;
            db = injectedContext;
        }

        public IActionResult Index()
        {
            var model = new HomeIndexViewModel
            {
                VisitorCount = (new Random()).Next(1, 100),
                Categories = db.Categories.ToList(),
                Products = db.Products.ToList()
            };
            return View(model);
        }


        [Microsoft.AspNetCore.Authorization.Authorize("Sales,Marketing")]
        public IActionResult SalesAndMarketEmployeesOnly()
        {
            return View();
        }

        //[Route("private")]
        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }


    }
}

打开Index.cshtml文件,注意@{}中包括的C#代码块。这些代码首先执行,可以存储一些数据,这些数据传递到共享布局文件

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

与Razor Pages一样,这里也有一个名为_ViewStart.cshtml文件

@{
    Layout = "_Layout";
}

在Views/Shared/_Layout.cshtml文件

这里读取了

image.png

模板页里面,使用了这个ViewData["Title"]

下面也使用了bootstrap的样式文件

image.png

下面很多css样式名,都是bootstrap里面的,这个可以从bootstrap网站学习


 image.png

有一些asp-开头的属性,如果想导航到Razor类库中的某个特性,那么可以使用asp-area指定名称

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)

当在任何包含serc属性的元素中,将asp-append-verwsion属性指定为true时,都将调用“图像标签助手”

图像标签助手的工作方式是自动附加从参考源文件的哈希值中生成的查询字符串值v,

如果site.js文件单个字节发生改变,哈希值也不同,因此,如果浏览器或cdn在缓存脚本文件,将会使用修改后的文件。

https://stackoverflow.com/questions/9692665/cache-busting-via-params.


启动时候,已经可以获取northwind数据,并且传递给页面了。

image.png

view端加个页面,遍历产品名

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <table class="table">
        <thead class="thead-inverse">
            <tr>
                <th>公司名字</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var p in Model.Products)
            {
                <tr><th>@p.ProductName</th></tr>
            }
        </tbody>
    </table>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

image.png


自定义ASP.NET Core MVC网站

删掉Index.cshtml的代码


打开wwwroot\css的site.css文件

添加一个样式

#newspaper {
column-count:3;
}

书上代码:https://github.com/markjprice/cs8dotnetcore3

wwwroot文件夹新建一个images文件夹,

然后打开下载完的代码,找到这个文件夹的图片,复制到images下

image.png


Razor语法

@object.property语法 取值

单个简单,如果多个值结合使用,比如计算,需要用@( C#代码 ) 

@{
    ViewData["Title"] = "Home Page";
    var vtest = new
    {
        a1 = 100.00,
        a2 = 365
    };
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    @*<table class="table">
        <thead class="thead-inverse">
            <tr>
                <th>公司名字</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var p in Model.Products)
            {
                <tr><th>@p.ProductName</th></tr>
            }
        </tbody>
    </table>*@
<p>Learn about @(vtest.a1*vtest.a2) <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

定义类型化视图

在cshtml页面上使用@model 类型,前面是命名空间,你也可以@using先导入命名空间

image.png

上面是有智能提示的

上面定义好了,页面上是使用@Model使用,第一个M是大写字母。


编写Index.cshtml代码

(html里面混编razor,要用@符号,多个符号的就用@( ),那么@{}里面的代码可以直接写html,那个就是字符串)

路径都有提示,@model导入后,类型后面的属性名都有提示

image.png

image.png


代码如下:

@model NorthwindMvc.Models.HomeIndexViewModel
@{
    ViewData["Title"] = "Home Page";
    string currentItem = "";
}

<div id="categories" class="carousel slide" data-ride="carousel" data-interval="3000" data-keyboard="true">
    <ol class="carousel-indicators">
        @for (int c = 0; c < Model.Categories.Count; c++)
        {
            if (c == 0)
            {
                currentItem = "active";
            }
            else
            {
                currentItem = "";
            }
            <li data-target="#categories" data-slide-to="@c" class="@currentItem"></li>
        }
    </ol>
    <div class="carousel-inner">
        @for (int c = 0; c < Model.Categories.Count; c++)
        {
            if (c == 0)
            {
                currentItem = "active";
            }
            else
            {
                currentItem = "";
            }
            <div class="carousel-item @currentItem">
                <img class="d-block w-100" src="~/images/category@(Model.Categories[c].CategoryID).jpeg" alt="@Model.Categories[c].CategoryName" />
                <div class="carousel-caption d-none d-md-block">
                    <h2>@Model.Categories[c].CategoryName</h2>
                    <h3>@Model.Categories[c].Description</h3>
                    <p>
                        <a class="btn btn-primary" href="/category/@Model.Categories[c].CategoryID">查看</a>
                    </p>
                </div>
            </div>
        }
    </div>

    <a class="carousel-control-prev" href="#categories" role="button" data-slide="prev">
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
        <span class="sr-only">上一个</span>
    </a>
    <a class="carousel-control-next" href="#categories" role="button" data-slide="next">
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
        <span class="sr-only">下一个</span>
    </a>
</div>

<div class="row">
    <div class="col-md-12">
        <h1>Northwind</h1>
        <p class="lead">我们每个月有 @Model.VisitorCount 个访问者</p>
        <h2>产品</h2>
        <div class="newspaper">
            <ul>
                @foreach (var item in Model.Products)
                {
                    <li>
                        <a asp-controller="Home" asp-action="ProductDetail" asp-route-id="@item.ProductID">
                            @item.ProductName 的单价  @item.UnitPrice.Value.ToString("C") 
                        </a>
                    </li>
                }
            </ul>
        </div>
    </div>
</div>

然后一堆代码carousel开头的,就是bootstrap的轮播 控件,前端要求这么写的,有些动态内容我们都是@开头的代码拼接出来的。



运行完效果如下:

image.png

单击下面的产品的URL是 https://localhost:44386/Home/ProductDetail/1

image.png

由于ProductDetail这个action我们没写,所以显示404

我们使用asp-route-id就传递个id参数,当然这里你完全可以拼接一个完整的href属性


打开HomeController.cs 添加一个Action

        public IActionResult ProductDetail(int? id)
        {
            if (!id.HasValue)
            {
                return NotFound("无产品ID,无法获得产品详情");
            }

            var model = db.Products.SingleOrDefault(x=>x.ProductID==id);
            if (model == null)
            {
                return NotFound($"产品ID为{id}的产品找不到");
            }
            return View(model);
        }

右键添加一个对应的ProductDetail视图

image.png

image.png

image.png

@model NorthwindEntitesLib.Product
@{ 
    ViewData["Title"] = "产品详情 - " + Model.ProductName;
}
<h2>产品详情</h2>
<div>
    <dl class="dl-horizontal">
        <dt>产品ID</dt>
        <dd>@Model.ProductID</dd>
        <dt>产品名称</dt>
        <dd>@Model.ProductName</dd>
        <dt>类别ID</dt>
        <dd>@Model.CategoryID</dd>
        <dt>单价</dt>
        <dd>@Model.UnitPrice.Value.ToString("C")</dd>
        <dt>单位库存</dt>
        <dd>@Model.UnitsInStock</dd>
    </dl>
</div>

image.png

URL地址栏目

路由参数,就像id一样

/Home/ProductDetail/2

查询字符串参数

/Home/ProductDetail?id=2

表单参数,form里面的input的name属性对应 参数变量名

<form method="POST" action="/Home/ProductDetail">

    <input type="text" name="id"/>

    <input type="submit"/>

</form>


www.ayjs.net====================


模型绑定程序

模型绑定几乎可以填充以下任何类型:

简单类型:例如int,string,DateTime和bool

由class或者struct定义的复杂类型

集合类型,如数组和列表


接下来在Models文件夹中添加一个 Thing.cs的类文件

namespace NorthwindMvc.Models
{
    public class Thing {
        public int? ID { get; set; }
        public string Color { get; set; }
    }
}

在HomeController.cs添加两个操作方法,mvc会根据url的参数决定使用哪个方法

       public IActionResult ModelBinding()
        {
            return View();
        }
        public IActionResult ModelBinding(Thing thing)
        {
            return View(thing);
        }

右键方法名,添加同名字的视图,这次使用第二个

image.png

点击添加

image.png

第一次使用,要等一会,显示正在搭建基架

结束后,会自动生成跟方法名一致的cshtml页面

image.png

打开浏览器,导航到(每个人端口号可能不一样)

https://localhost:44386/home/modelbinding

第一次启动报错了

image.png

尽管C#编译器可以通过签名的不同来区分这两种方法,但是从HTTP的角度看,这两种方法都是潜在的匹配。我们使用不同的谓词来区分,当然你也可以换个名字


修改HomeController.cs第二个ModelBinding操作方法,为post请求

右键view,可以快速到controller中去

image.png

image.png

运行项目,点击提交按钮,效果如下

image.png


添加一个id

image.png

运行后

image.png

点击提交后

image.png

这里的id显示的是1,所以

如果有多个同名参数,那么表单参数具有最高优先级,而查询字符串参数具有最低优先级。


对于高级方案,可以实现IModelBinder接口创建自己的模型绑定程序,查看

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-5.0



验证模型

无论绑定了什么数据,任何绑定或验证错误都将存储在ControllerBase.ModelState中。下面对模型绑定应用一些验证规则,然后在视图中显示数据无效的消息。


修改Thing,使用注解方式添加验证

using System.ComponentModel.DataAnnotations;

namespace NorthwindMvc.Models
{
    public class Thing
    {
        [Range(1, 10)]
        public int? ID { get; set; }
        [Required]
        public string Color { get; set; }
    }
}

添加页面对应的Model,HomeModelBindingViewModel类用于显示错误信息

    public class HomeModelBindingViewModel
    {
        public Thing Thing { get; set; }
        public bool HasErrors { get; set; }
        public IEnumerable<string> ValidationErrors { get; set; }
    }

HomeController中修改

        public IActionResult ModelBinding()
        {
            return View();
        }
        [HttpPost]
        public IActionResult ModelBinding(Thing thing)
        {
            var model = new HomeModelBindingViewModel()
            {
                Thing = thing,
                HasErrors = !ModelState.IsValid,
                ValidationErrors = ModelState.Values.SelectMany(state => state.Errors).Select(error => error.ErrorMessage)
            };

            return View(model);
        }

post时候,会进入下面的ModelBinding(Thing thing)方法


现在我们需要在ModelBinding.cshtml页面下面 添加 显示错误信息的 代码,还要把顶部的model换成

image.png


修改后的代码:

@model NorthwindMvc.Models.HomeModelBindingViewModel
@{
    ViewData["Title"] = "Model Binding Demo";
}

<h1>@ViewData["Title"]</h1>
<div>在下面输入一种颜色</div>
<form method="POST" action="/home/modelbinding?id=3">
    <input value="1" name="id" />
    <input value="Red" name="color" />
    <input type="submit" />
</form>
@if (Model != null)
{
    <h2>提交的颜色</h2>
    <dl class="dl-horizontal">
        <dt>Model.Thing.ID</dt>
        <dd>@Model.Thing.ID</dd>
        <dt>Model.Thing.Color</dt>
        <dd>@Model.Thing.Color</dd>
    </dl>

    @if (Model.HasErrors)
    {
        <div>
            @foreach (var msg in Model.ValidationErrors)
            {
                <div class="alert alert-danger" role="alert">@msg</div>
            }
        </div>
    }

}

输入 20,颜色保持空

image.png

点击提交

image.png


关于模型验证更多信息: http://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation



视图辅助方法

@Html提供了一些方法

比如ActionLink

AntiForgeryToken:在Form元素中用来插入<hidden>元素,当提交表单时,可验证<hidden>元素包含的防伪令牌。

Display,DisplayFor,DisplayForModel

Editor,EditorFor,EditorForModel

Encode用来将对象或者字符串安全地编码为HTML

Raw呈现字符串值

PartialAsync和RenderPartialAsync用来为分部视图生成HTML标记。你可以选择传递模型和视图数据。

更多HTMLHelper类的信息: https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.viewfeatures.htmlhelper?view=aspnetcore-5.0



下面在HomeController.cs创建一个新的操作方法ProductsThatCostMoreThan(decimal? price)

        public IActionResult ProductsThatCostMoreThan(decimal? price)
        {
            if (!price.HasValue)
            {
                return NotFound("你必须传递一个产品的价格");
            }
            IEnumerable<Product> model = db.Products.Include(x=>x.Category).Include(p=>p.Supplier).AsEnumerable().Where(p=>p.UnitPrice>price);
            if (model.Count() == 0)
            {
                return NotFound($"没有价格大于{price:C}的产品");
            }
            ViewData["MaxPrice"] = price.Value.ToString("C");
            return View(model);

        }

同操作,添加对应的ProductsThatCostMoreThan.cshtml

@model IEnumerable<NorthwindEntitesLib.Product>
@{ 
    ViewData["Title"]="产品价格大于"+ViewData["MaxPrice"];
}
<h2>"产品价格大于"@ViewData["MaxPrice"]</h2>
<table class="table">
    <tr>
        <th>类别</th>
        <th>供应商公司名字</th>
        <th>产品名称</th>
        <th>单价</th>
        <th>单位库存</th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <th>@Html.DisplayFor(m=>item.Category.CategoryName)</th>
            <th>@Html.DisplayFor(m => item.Supplier.CompanyName)</th>
            <th>@Html.DisplayFor(m => item.ProductName)</th>
            <th>@Html.DisplayFor(m => item.UnitPrice)</th>
            <th>@Html.DisplayFor(m => item.UnitsInStock)</th>
        </tr>
    }
</table>

接下来在Index.cshtml添加测试入口

        <form asp-action="ProductsThatCostMoreThan" method="get">
            <input placeholder="输入产品价格" name="price" />
            <input type="submit" />
        </form>

image.png

www.ayjs.net====================


运行后

image.png

输入50,单击提交,效果如下:

image.png


使用异步任务提高可伸缩性

当HTTP请求到达Web服务器时,就从线程池中,分配线程来处理请求。但如果线程必须等待资源,就阻止处理任何其他传入的请求。如果一个网站同时收到的请求数多于线程池中的线程数,其中一些请求将响应服务器超时错误503 Service Unavailable

锁定的线程没有做什么有用的工作。它们可以处理其他请求之一,但提前是网站实现了异步代码。

每当线程在等待需要的资源时,就可以返回线程池并处理不同的传入请求,从而提高网站的可伸缩性,也就是说,增加网站可以同时处理的请求的数量。

为什么不创建更大的线程池呢?在现代操作系统中,线程池中的每个线程都有1MB的大小的堆栈。异步方法使用的内存较少,并且消除了在线程池中创建新线程的需求。但这需要时间。向线程池中添加新线程的速度通常为每两秒添加1个,与异步线程之间切换相比,时间有些太长了。


打开HomeController类,导入System.Threading.Tasks名称空间

修改代码如下

        public async Task<IActionResult> Index()
        {
            var model = new HomeIndexViewModel
            {
                VisitorCount = (new Random()).Next(1, 100),
                Categories = await db.Categories.ToListAsync(),
                Products = await db.Products.ToListAsync()
            };
            return View(model);
        }

image.png


类似的方法修改ProductDetail

   public async Task<IActionResult> ProductDetail(int? id)
        {
            if (!id.HasValue)
            {
                return NotFound("无产品ID,无法获得产品详情");
            }

            var model =await db.Products.SingleOrDefaultAsync(x => x.ProductID == id);
            if (model == null)
            {
                return NotFound($"产品ID为{id}的产品找不到");
            }
            return View(model);
        }

运行项目后,显示效果是一样的,但现在剋有更好地拓展


使用其他项目模板

安装.NET Core SDK时,不会附带安装许多项目模板。

终端输入dotnet new  --help可以显示当前安装的项目模板列表

在vs2019还有些 React和Angular的创建SPA的项目模板

image.png

image.png


安装其他模板

打开 http://dotnetnew.azurewebsites.net

比如输入vue

image.png

搜索结果

image.png

可通过以下链接查看更多模板

https://github.com/dotnet/templating/wiki/Available-templates-for-dotnet-new



www.ayjs.net====================

推荐您阅读更多有关于“C#8.0core3,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

合肥科大智能常年招聘C# .NET CORE,vue前端,JAVA开发,有想换工作的私聊我AY唯一QQ:875556003和AY交流

抖音号:wpfui 工作是wpf,不接活,目前主要折腾maui

AYUI8社区版Github地址:前往获取

杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2010年开始web开发,2015年1月17日开始,兴趣学习研究WPF

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表