ASP.NET Core 一步步搭建个人网站(4)_主页和登录验证

news/2024/5/21 1:16:18/文章来源:https://blog.csdn.net/weixin_34302561/article/details/89655991

上章节我们已经定制好动态配置的菜单,用户登录网站的第一步就是进入首页内容,那我们先搭建一下我们的首页内容。想着自己的网站内容主要是个人博客类型,所以,首页就展示博主本人的一些基本信息吧,哈哈。当然,做成静态的界面很简单,直接将信息填进html中就行了,基本没有什么技术含量,那我们这里要做成可配置的:将个人信息配置在json文件中(也可以存储在数据库,考虑信息内容结构的不可预期性和易变性,这里不采用数据库保存)。这样,以后我们要更新主页上的信息时,就不用编译发布网站,只要修改对应的json配置文件即可。

.NET Core 配置机制介绍

提到“配置”二字,我们脑海中会立马浮现出两个特殊文件,那就是我们再熟悉不过的app.config和web.config,一直以来我们已经习惯了将结构化的配置信息定义在这两个文件之中。到了.NET Core的时候,很多我们习以为常的东西都发生了改变,其中也包括定义配置的方式。有兴趣的同学可以移步官方文档介绍:.net core 配置

.NET Core不仅支持以键-值对的形式、结构化的形式读取相关的配置信息(这里自己去研究,不在祥述),更重要的是,如今可以将定义的结构化配置绑定为对象。之前我们必须逐条的读取配置信息,如果配置项太多的话,读取配置项其实是一项非常繁琐的工作。现在只用再定义对应结构的Option对象,框架自动帮我们绑定配置信息到这个对象,我们直接访问对象中的属性即可。除此之外,.NET Core采用依赖注入的方式来使用Option模型,这样我们就和方便的在需要的地方使用配置信息了。

接下来看具体怎么使用,首先,在项目中增加json配置文件,这里结构如下:

我们按照Json的格式,定义一个接收配置信息的类(结构完全等同json中的定义)

 1 /// <summary>
 2 /// 个人资料
 3 /// </summary>
 4 public class MyProfile
 5 {
 6     public IEnumerable<Project> Projects { set; get; }
 7 }
 8 
 9 /// <summary>
10 /// 项目经历
11 /// </summary>
12 public class Project
13 {
14     /// <summary>
15     /// 持续至日期
16     /// </summary>
17     public string LastToDate { set; get; }
18     /// <summary>
19     /// 项目名称
20     /// </summary>
21     public string Name { set; get; }
22     /// <summary>
23     /// 持续时间
24     /// </summary>
25     public int Lasting { set; get; }
26     /// <summary>
27     /// 所在公司
28     /// </summary>
29     public string Company { set; get; }
30     /// <summary>
31     /// 项目职务
32     /// </summary>
33     public string MyTitle { set; get; }
34     /// <summary>
35     /// 项目职责
36     /// </summary>
37     public string MyDuty { set; get; }
38     /// <summary>
39     /// 项目技术
40     /// </summary>
41     public string Technology { set; get; }
42     /// <summary>
43     /// 项目规格
44     /// </summary>
45     public int NumOfPeople { set; get; }
46     /// <summary>
47     /// 项目描述
48     /// </summary>
49     public IEnumerable<string> ProjectDescs { set; get; }
50     /// <summary>
51     /// 项目图片
52     /// </summary>
53     public IEnumerable<string> ProjectImgs { set; get; }
54 }

那怎么建立json数据和对象之间的映射呢,见证奇迹的时候到了,在Startup.cs文件中ConfigureServices方法中,增加以下代码:

1 var builder = new ConfigurationBuilder()
2                 .SetBasePath(Directory.GetCurrentDirectory())
3                 .AddJsonFile("Datas/Config/MyProfile.json");
4 
5 var config = builder.Build();
6 
7 services.Configure<MyProfile>(config.GetSection("MyProfile"));

在需要使用配置信息地方通过构造器注册,可以看到相关信息完整的加载到对象中,是不是新的配置系统显得更加轻量级,具有更好的扩展性,并且支持多样化的数据源。

个人信息展示

有了可配置的个人信息数据,我们只需要在主页上将之展示出来即可,后台管理--菜单管理,添加一个主页菜单,排序最前,设置访问路径/Home/Index,图标样式,保存后左侧导航便出现新增的主页菜单项。在HomeController控制器的Index方法中,已经读取到个人信息数据,返回前端渲染,效果如下:

 1 <div class="tab-pane active" id="timeline">
 2     <ul class="timeline timeline-inverse">
 3 
 4         @foreach (var project in Model.Projects.Reverse())
 5         {
 6             <li class="time-label">
 7                 <span class="bg-light-blue">@project.LastToDate</span>
 8             </li>
 9             <li>
10                 <i class="fa fa-tags bg-blue"></i>
11                 <div class="timeline-item">
12                     <span class="time">持续时间:@(project.Lasting)个月 <i class="fa fa-clock-o"></i></span>
13                     <h3 class="timeline-header">
14                         <a>项目名称</a> @project.Name
15                     </h3>
16                     <div class="timeline-body">
17                         <p class="text-muted">所在公司: @project.Company</p>
18                         <p class="text-muted">项目职务: @project.MyTitle</p>
19                         <p class="text-muted">项目职责: @project.MyDuty</p>
20                         <p class="text-muted">项目技术: @project.Technology</p>
21                     </div>
22                     <div class="timeline-footer">
23                         <a class="btn btn-primary btn-xs">更多 >></a>
24                     </div>
25                 </div>
26             </li>
27             <li>
28                 <i class="fa fa-thumb-tack bg-aqua"></i>
29                 <div class="timeline-item">
30                     <span class="time">规模:@(project.NumOfPeople)个人 <i class="fa fa-cube"></i></span>
31                     <h3 class="timeline-header no-border">
32                         <a>项目描述</a>
33                     </h3>
34                     <div class="timeline-body">
35                         @if (project.ProjectDescs != null)
36                         {
37 
38                             var descIndex = 0;
39 
40                             foreach (var projectDesc in project.ProjectDescs)
41                             {
42                                 <p class="text-muted">@(++descIndex). @projectDesc.</p>
43                             }
44                         }
45                     </div>
46                 </div>
47             </li>
48             if (project.ProjectImgs != null)
49             {
50                 <li>
51                     <i class="fa fa-camera bg-purple"></i>
52                     <div class="timeline-item">
53                         <span class="time"><i class="fa fa-photo"></i></span>
54                         <h3 class="timeline-header">
55                             <a>效果预览</a>
56                         </h3>
57                         <div class="timeline-body">
58                             <div class="row">
59                                 @foreach (var projectImg in project.ProjectImgs)
60                                 {
61                                     <div class="col-sm-6 col-md-4">
62                                         <img style="cursor: pointer; height: 150px;" src="@projectImg"
63                                              alt="..." class="img-responsive thumbnail center-block img-more">
64                                     </div>
65                                 }
66                             </div>
67                         </div>
68                     </div>
69                 </li>
70             }
71 
72         }
73 
74         <!-- start -->
75         <li class="time-label">
76             <span class="bg-green">2009.02</span>
77         </li>
78         <li>
79             <i class="fa fa-clock-o bg-gray"></i>
80         </li>
81     </ul>
82 </div>

目前图片是用压缩后的缩略图显示的(为了网页快速加载),可能用户想要展开看原始图,所有我们这块可以优化一下,点击缩略图,弹出模态框,展示原始尺寸图片。ok,主页部分大功告成,后台修改json文件配置,我们的主页内容也和方便的更新了。

 1 <script>
 2     $('.img-more').click(function () {
 3         var file = $(this).attr('src')
 4         var fileNames = file.split('.')
 5         $("#myModal").find("#img_show").html("<image src='" +
 6             fileNames[0] + '-lg.' + fileNames[1] +
 7             "' class='carousel-inner img-responsive img-rounded' />")
 8         $("#myModal").modal();
 9     })
10 </script>

登录验证功能

还记得第2章内容吗,我们已经实现了用户的注册和登录,但是目前没有做相关的登录验证和权限管理(权限管理以后等后面完成用户角色单独开一章说,本章主要说一下登录验证)。比如我们注销用户时,再次通过浏览器链接,输入http://localhost:16546/Configuration/Menu/Index,就可以跳过登录,直接访问菜单界面。这块我们要自己实现的话,不外乎2种方案:

第1种:定义一个公共的控制器,其他所有的控制器继承它,公共的控制器实现重写如下方法:

 1 public class AuthenticationControllor : Controller
 2 {
 3     protected override void OnActionExecuting(ActionExecutingContext filterContext)
 4     {
 5         if (filterContext.HttpContext.Session["username"] == null)
 6             filterContext.Result = new RedirectToRouteResult("Login", new RouteValueDictionary { { "from", Request.Url.ToString() } });
 7             
 8         base.OnActionExecuting(filterContext);
 9     }
10 }

第2种:定义认证特性,继承ActionFilterAttribute,在需要验证的地方,增加属性认证:

 1 // 登录认证特性
 2 public class AuthenticationAttribute : ActionFilterAttribute
 3 {
 4     public override void OnActionExecuting(ActionExecutingContext filterContext)
 5     {
 6         if (filterContext.HttpContext.Session["username"] == null)
 7             filterContext.Result = new RedirectToRouteResult("Login", new RouteValueDictionary { { "from", Request.Url.ToString() } });
 8             
 9         base.OnActionExecuting(filterContext);
10     }
11 }

那我们采用哪种方法呢?都不用,哈哈,因为Indentity帮我们已经完成了所有的认证工作,直接在需要验证的控制器或方法上,增加属性过滤器[Authorize]即可。

我们再试验下,注销登录后,我们浏览器中输入菜单界面地址链接,网站判断此时尚未登录,就会跳转到登录界面。用户输入登录信息无误后,跳转到需要访问的菜单界面。

 

加载Loading效果和form表单重复提交防护

 上图我们可以看到,每次页面加载的时候页面头部会出现一条进度条和一个转动的loading,这样给用户的体验会很好,这是怎么实现的呢。其实AdminLTE已经提供了很方便的使用:首先我们在母版页Layout.cshtml引入<script src="~/lib/AdminLTE/plugins/pace/pace.js"></script>,然后加入以下脚本,就实现上述的效果,很简单吧:

1 //ajax请求Pace效果
2 $(document).ajaxStart(function () {
3     Pace.restart()
4 })

之前实现的菜单管理,存在一个小问题,比如用户在保存的时候,网速慢或服务器反应延迟的情况,用户等不急再次点击form表单中的提交按钮,就会造成重复提交的场景,一般会导致异常。虽然说在后台增加逻辑判断也可以解决,但是重复提交造成的异常各种各样,要就增加各种验证,得不偿失。我的想法是在前端提交后,服务器未返回结果之前,将提交按钮置为不可用状态,这样用户无法再次点击,从而避免服务器端异常。但是还有个问题,必须在jquery前端验证之后,才能开始置为不可用,否则前端验证失效。所以我们修改下jquery前端验证的默认的submitHandler。每当用户点击提交按钮时,会首先触发前端验证,验证不通过,直接显示错误提示;验证通过后,将按钮置不可用,直到服务器返回结果。

1 //防止重复提交
2 $.validator.setDefaults({
3     submitHandler: function (form) {
4         $(form).find('[type="submit"]').attr('disabled', true);
5         form.submit();
6     }
7 });

404,500等错误页面提示

之前我们建了一些菜单项,因为没有指定访问路径,点击后会有404错误;另外,一些服务器异常,网页抛出500错误。这些需要捕获一下,并提供友好的页面显示给用户。在Startup.cs文件Configure方法中,配置如下:

 1 if (env.IsDevelopment())
 2 {
 3     app.UseExceptionHandler("/Home/Error/500");
 4     app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
 5 
 6     app.UseDeveloperExceptionPage();
 7     app.UseBrowserLink();
 8     app.UseDatabaseErrorPage();
 9 }
10 else
11 {
12     app.UseExceptionHandler("/Home/Error/500");
13     app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
14 }

对应的控制器代码更新如下:

1 [Route("Home/Error/{statusCode}")]
2 public IActionResult Error(int statusCode)
3 {
4     return View(new ErrorViewModel
5     {
6         StatusCode = statusCode,
7         RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
8     });
9 }

对应视图代码也需要更新一下:

 1 @model MyWebSite.ViewModels.ErrorViewModel
 2 @{
 3     ViewData["Title"] = "错误";
 4 }
 5 <div class="error-page" style="margin-top: 100px;">
 6     @if (Model.StatusCode == 500)
 7     {
 8         <!-- 500类型错误 -->
 9         <h2 class="headline text-red"> @Model.StatusCode</h2>
10 
11         <div class="error-content">
12             <h3>
13                 <i class="fa fa-warning text-red"></i> Oops! Something went wrong.
14             </h3>
15             <div>
16                 StatusCode:<code>@Model.StatusCode</code>
17             </div>
18             <div>
19                 Request ID: <code>@Model.RequestId</code>
20             </div>
21             <p>
22                 We will work on fixing that right away.
23                 Meanwhile, you may <a asp-area="" asp-controller="Home" asp-action="Index">return to index</a> or try using the search form.
24             </p>
25             <form class="search-form">
26                 <div class="input-group">
27                     <input type="text" name="search" class="form-control" placeholder="Search">
28                     <div class="input-group-btn">
29                         <button type="submit" name="submit" class="btn btn-danger btn-flat">
30                             <i class="fa fa-search"></i>
31                         </button>
32                     </div>
33                 </div>
34             </form>
35         </div>
36     }
37     else
38     {
39         <!-- 其他类型错误 -->
40         <h2 class="headline text-yellow"> @Model.StatusCode</h2>
41 
42         <div class="error-content">
43             <h3>
44                 <i class="fa fa-warning text-yellow"></i> Oops! Page not found.
45             </h3>
46             <div>
47                 StatusCode:<code>@Model.StatusCode</code>
48             </div>
49             <div>
50                 Request ID: <code>@Model.RequestId</code>
51             </div>
52             <p>
53                 We could not find the page you were looking for.
54                 Meanwhile, you may <a asp-area="" asp-controller="Home" asp-action="Index">return to index</a> or try using the search form.
55             </p>
56             <form class="search-form">
57                 <div class="input-group">
58                     <input type="text" name="search" class="form-control" placeholder="Search">
59                     <div class="input-group-btn">
60                         <button type="submit" name="submit" class="btn btn-warning btn-flat">
61                             <i class="fa fa-search"></i>
62                         </button>
63                     </div>
64                 </div>
65             </form>
66         </div>
67     }
68 </div>

小结

  以上,这期关于网站的调整已介绍完毕,最后,后台管理--菜单管理,添加对应博客链接的菜单项,为了方便用户通过链接访问我的博客,看下演示效果吧:

 

img_8f0a90f3cbaa0e044fb8bf7b13c4317b.jpe

文章作者:原子蛋
文章出处:https://www.cnblogs.com/lizzie-xhu/
个人网站:https://www.lancel0t.cn/
个人博客:https://blog.lancel0t.cn/
微信公众号:原子蛋Live+
扫一扫左侧的二维码(或者长按识别二维码),关注本人微信公共号,获取更多资源。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_833115.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java裸写爬虫技术,运用多线程技术,高效爬取某个医疗机构网站数据

最近喜欢上了数据的庞大的感觉&#xff0c;就爬取了一下某个医疗机构网站医疗数据&#xff0c;由于数据量庞大&#xff0c;只爬取了江西省的各个市的各个医院的各个科室的各个科室。中各种信息。其中用的持久层技术是hibernate框架&#xff0c;和用到一些ioc技术。话不多说&…

解决登录同一个网站,连接失败

2019独角兽企业重金招聘Python工程师标准>>> 程序报错 MaxRetryError: HTTPConnectionPool(host127.0.0.1, port53742): Max retries exceeded with url: /session/7e0b607f-022e-4464-9eb3-461844f59b84/window/maximize (Caused by NewConnectionError(<urllib…

Awesome 书籍源码论文软件下载网站整理

software.informerAAAI会议论文下载Packt出版商的书籍开源代码&#xff0c;目前已经超过6600个仓库

在IIS管理器添加网站

1.添加物理路径 2.跨域问题解决方案 A.点击所创网站出现如图所示&#xff0c;双击HTTP响应标头 B.右键–“添加”&#xff0c;添加以下2条&#xff1a; Access-Control-Allow-Headers&#xff1a;Content-Type, api_key, Authorization Access-Control-Allow-Origin&#xf…

超全Inventor 3d模型素材网站整理

家人们&#xff0c;最近我找到了一个很好用的Inventor 3d模型免费素材网站 本人曾经也是废大把时间寻找资源&#xff0c;质量还不咋地&#xff0c;但是通过朋友安利&#xff0c;知道了一个很好的网站&#xff1a;爱给网&#xff0c;里面资源内容丰富&#xff0c;并且可以一键下…

良心安利电梯过道su模型素材网站

电梯过道su模型类资源应该算是素材类网站中必不可少的资源类型了吧~今天给大家推荐超好用&#xff0c;免费质量高的素材噢&#xff0c;让你坐拥海量资源同时又不撞款&#xff01; 免费资源最多&#xff0c;又全面的&#xff0c;那就是 爱给网啦&#xff01; 它有很多素材&…

宝藏又小众的灯饰装修设计素材网站分享

今天小编针对灯饰装修设计素材为大家整理了很多内容哦&#xff0c;肯定有需要的小伙伴吧&#xff0c;实用、免费、优质的素材谁又不心动呢&#xff01;赶紧码住&#xff01; 免费资源最多&#xff0c;又全面的&#xff0c;那就是 爱给网啦&#xff01; 它有很多素材&#xff0…

超全教育cc0高清摄影图片素材网站整理

天天各大网站找教育cc0高清摄影图片素材&#xff1f;最后空手而归&#xff1f;今天为大家推荐教育cc0高清摄影图片素材网站&#xff0c;质量上乘适合资源慌缺的你&#xff0c;话不多说准备开始收藏吧&#xff01; 接下来就给大家介绍一下我珍藏已久的网站&#xff0c;我的工作…

超全园林 景观cc0高清摄影图片素材网站整理

看到大家都在问园林 景观cc0高清摄影图片素材&#xff0c;既要免费又要质量好&#xff0c;数量还要多&#xff0c;小编好不容易挖到了宝藏素材网站哦&#xff0c;资源优质数量庞大&#xff0c;使用体验也很好&#xff0c;要是需要的话&#xff0c;赶紧看一看&#xff0c;小编会…

良心安利食物 美食免抠元素素材网站

天天各大网站找食物 美食免抠元素素材&#xff1f;最后空手而归&#xff1f;今天为大家推荐食物 美食免抠元素素材网站&#xff0c;质量上乘适合资源慌缺的你&#xff0c;话不多说准备开始收藏吧&#xff01; 本人曾经也是废大把时间寻找资源&#xff0c;质量还不咋地&#xf…

宝藏又小众的线条免抠元素素材网站分享

最近看到很多朋友吐槽线条免抠元素素材不好找&#xff0c;有时花了大把时间却没找到合适的&#xff0c;而且有的时候会涉及到各种问题等&#xff0c;不仅工作效率降低&#xff0c;还闹心郁闷&#xff0c;所以今天就给大家分享一下小编自己在亲身体验和搜寻网站中&#xff0c;收…

最良心的网站可以良心到什么程度?

之前就在爱给网下载过音频&#xff0c;最近点进爱给网首页&#xff0c;发现爱给网上新了一系列在线小工具。不收费&#xff0c;完全免费&#xff0c;没有广告&#xff0c;页面简约&#xff0c;真的是很惊喜&#xff0c;迫不及待分享给大家&#xff0c;今天先跟大家分享一下我使…

良心安利企业内部管理设计模板素材网站

今天小编针对企业内部管理设计模板素材为大家整理了很多内容哦&#xff0c;肯定有需要的小伙伴吧&#xff0c;实用、免费、优质的素材谁又不心动呢&#xff01;赶紧码住&#xff01; 免费资源最多&#xff0c;又全面的网站&#xff0c;我找到啦&#xff01;&#xff01;它有很…

宝藏又小众的家具构件ps后期素材素材网站分享

今天小编针对家具构件ps后期素材素材为大家整理了很多内容哦&#xff0c;肯定有需要的小伙伴吧&#xff0c;实用、免费、优质的素材谁又不心动呢&#xff01;赶紧码住&#xff01; 本人曾经也是废大把时间寻找资源&#xff0c;质量还不咋地&#xff0c;但是通过朋友安利&#…

超全荒地UE4素材网站整理

关于荒地UE4素材肯定是很多人需要的东西&#xff0c;但是在找的时候总是会碰到各种问题&#xff0c;小编为大家总结了很多种类齐全&#xff0c;免费好用的素材&#xff0c;赶紧围观&#xff01; 本人曾经也是废大把时间寻找资源&#xff0c;质量还不咋地&#xff0c;但是通过朋…

超全在线客服网页特效素材网站整理

前方注意咯&#xff01;建议先收藏再看哦&#xff01;为大家整理在线客服网页特效素材&#xff0c;总有满足你需求的一款&#xff0c;除此之外&#xff0c;免费&#xff0c;资源质量好&#xff0c;一键打包下载&#xff0c;你还不心动吗&#xff1f; 因为小编的工作原因&#…

aspnet网站开发实例_新课来啦!利用电脑建立个人网站

现在是已经晚上10点半了&#xff0c;差不多快到了“不睡不要脸”的时间了&#xff0c;现在发送文章有些晚了&#xff0c;因为我制作《利用电脑建立网站》遭到了质疑&#xff0c;有人吐槽利用电脑建立网站速度慢&#xff0c;作用不大。我于是想找个免费的或者便宜的空间试试&…

dseo13b打开自动消失_自动门中的检测与延时预防事故,分享控制案例

你知道吗&#xff1f;检测和延时是预防事故发生的有效措施&#xff0c;可以说不可能有绝对完备的安全措施&#xff0c;但这里所说的两项技术——检测和延时&#xff0c;可以加强安全措施。一扇门的关上和打开&#xff0c;它的动作看起来是不是很简单&#xff1f;我们想一下&…

hexo 菜单_GitHub+Hexo+NexT搭建个人网站全流程及魔改记录

写在前面本篇是关于利用GitHub Pages服务&#xff0c;使用Hexo框架以及NexT主题搭建个人网站的全流程的记录&#xff0c;本着高效工作的原则做了一些自定义修改来优化个人网站。本文原文发布在我的个人博客zhangypcn.github.io&#xff0c;欢迎访问。https://zhangypcn.github.…

企业域名备案流程_企业内部撬装加油站是否需要审批及备案?建站手续流程是怎样的?...

企业内部撬装加油站可以为企业省去很多不必要的开支&#xff0c;所以很多用油量很大的企业都想拥有属于自己的加油站&#xff0c;一是可以节省用油成本&#xff0c;二是可以节省很多的车辆管理成本&#xff0c;如今国内许多城市逐渐有撬装加油站拔地而起&#xff0c;那么&#…