首页 科技正文

“忻州”租房网:ASP.NET Core Razor Pages 『初探』

admin 科技 2020-04-28 66 0

最近新建 Asp.net Core MVC <项目>「‘<的>’」时刻不小心选错了个模板,发现了一种新「‘<的>’」<项目>模板。「它使用」cshtml(视)图模板,‘然则没有’Controller《文件》夹。厥后才发现这是ASP.NET Core框架新推出「‘<的>’」Razor Pages手艺。

什么是Razor Pages

“Razor Pages 使编码加倍简朴加倍富有生产力”这是微软说「‘<的>’」==!。Razor Pages 简化了传统「‘<的>’」mvc模式,仅仅使用视图跟模子来完成网页「‘<的>’」渲染跟营业逻辑「‘<的>’」处置。模子里包罗了数据跟方式,通过绑定手艺跟视图确立联系,这就(有点(像))‘服务’端「‘<的>’」绑定手艺。下面使用一个尺度「‘<的>’」CRUD〖示例来演示〗Razor Pages「‘<的>’」开发,而且简朴「‘<的>’」探索一下它是若何事情「‘<的>’」。

新建Razor Pages<项目>

在visual studio中新建Razor Pages<项目>。

<项目>结构

新建<项目>「‘<的>’」目录结构比MVC<项目>简朴。它没有Controllers目录,Pages(有点(像))MVC<项目>「‘<的>’」Views目录,内里存放了cshtml模板。随便点开一个cshtml《文件》,“发现它都包罗了一个”cs《文件》。这是跟MVC<项目>最大「‘<的>’」差别,这个结构让人回忆起那古老「‘<的>’」WebForm手艺,o(╥﹏╥)o 。

新建Razor Page

我们模拟开发一个学生治理系统。一共包罗4个〖页面〗:列表〖页面〗、【新增〖页面〗】、《{“ 修改[”}》〖页面〗、删除〖页面〗。首先我们新建一个列表〖页面〗。
在Pages目录下面新建Student目录。在Student〖《目录下新建》〗4个Razor page名叫:List、Add、Update、Delete。

建好后目录结构是这样:

模拟数据接见仓储

由于这是个演示<项目>,以是我们使用静态变量来简朴模拟下数据持久。
在<项目>下新建一个Data目录,在〖《目录下新建》〗Student实体类:

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public string Class { get; set; }

        public int Age { get; set; }

        public string Sex { get; set; }
    }

在Data〖《目录下新建》〗IStudentRepository跟StudentRepository类:

    public interface IStudentRepository
    {
        List<Student> List();

        Student Get(int id);

        bool Add(Student student);

        bool Update(Student student);

        bool Delete(int id);
    }

    public class StudentRepository : IStudentRepository
    {
        private static List<Student> Students = new List<Student> {
                new Student{ Id=1, Name="小红", Age=10, Class="1 班[", Sex="女"},
                new Student{ Id=2, Name="小明", Age=11, Class="2 班[", Sex="男"},
                new Student{ Id=3, Name="小强", Age=12, Class="3 班[", Sex="男"}
        };

        public bool Add(Student student)
        {
            Students.Add(student);

            return true;
        }

        public bool Delete(int id)
        {
            var stu = Students.FirstOrDefault(s => s.Id == id);
            if (stu != null)
            {
                Students.Remove(stu);
            }

            return true;
        }

        public Student Get(int id)
        {
            return Students.FirstOrDefault(s=>s.Id == id);
        }

        public List<Student> List()
        {
            return Students;
        }

        public bool Update(Student student)
        {
            var stu = Students.FirstOrDefault(s=>s.Id == student.Id);
            if (stu != null)
            {
                Students.Remove(stu);
            }

            Students.Add(student);
            return true;
        }
    }

我们新建了一个IRepository接口,内里有几个基本「‘<的>’」crud「‘<的>’」方式。然后新建一个实现类,{而且使}用静态变量保留数据,模拟数据持久化。
固然还得在DI容器中注册一下:

  public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            //注册repository
            services.AddScoped<IStudentRepository, StudentRepository>();
        }

实现列表(student/list)〖页面〗

列表〖页面〗用来展现所有「‘<的>’」学生信息。
《{“ 修改[”}》ListModel类:

    public class ListModel : PageModel
    {
        private readonly IStudentRepository _studentRepository;
        public List<Student> Students { get; set; }
        public ListModel(IStudentRepository studentRepository) 
        {
            _studentRepository = studentRepository;
        }

        public void OnGet()
        {
            Students = _studentRepository.List();
        }
    }

《{“ 修改[”}》List.cshtml模板:

@page
@model RazorPageCRUD.ListModel
@{
    ViewData["Title"] = "List";
}

<h1>List</h1>

<p>
    <a class="btn btn-primary" asp-page="Add">Add</a>
</p>
<table class="table">
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Age</th>
        <th>Class</th>
        <th>Sex</th>
        <th></th>
    </tr>
    @foreach (var student in Model.Students)
    {
        <tr>
            <td>@student.Id</td>
            <td>@student.Name</td>
            <td>@student.Age</td>
            <td>@student.Class</td>
            <td>@student.Sex</td>
            <td>
                <a class="btn btn-primary" asp-page="Update" asp-route-id="@student.Id">Update</a>
                <a class="btn btn-danger" href="/student/delete?id=@student.Id" >Delete</a>
            </td>
        </tr>
    }

</table>

ListModel『类夹杂了』MVC「‘<的>’」Controller跟Model「‘<的>’」观点。它本身可以认为是MVC内里「‘<的>’」谁人Model,它包罗「‘<的>’」数据可以被razor试图引擎使用,用来天生html,{好比}它「‘<的>’」Students属性;<然则它又包罗方式>,可以用来处置营业逻辑,这个方式可以认为是Controller中「‘<的>’」Action。方式通过特殊「‘<的>’」前缀来跟前端「‘<的>’」请求做绑定,{好比}OnGet方式就是对Get请求作出响应,OnPost则是对Post请求作出响应。
运行一下而且接见/student/list:

列表〖页面〗可以正常运行了。

使用asp-page举行〖页面〗间导航

列表〖页面〗〖上〗有几个按钮,{好比}新增、删除等,点击「‘<的>’」时刻希望跳转至差别「‘<的>’」〖页面〗,可以使用asp-page属性来实现。asp-page属性不是html自带「‘<的>’」属性,显然这是Razor Pages为我们提供「‘<的>’」。

<p>
    <a class="btn btn-primary" asp-page="Add">Add</a>
</p>

〖上〗面「‘<的>’」代码在a元素〖上〗添加了asp-page="Add",示意点击这个a毗邻会跳转至同级目录「‘<的>’」Add〖页面〗。html〖页面〗之间「‘<的>’」导航不管框架怎么封装无非就是url之间「‘<的>’」跳转。<显然这里>asp-page「最后」会翻译成一个url,(看看天生「‘<的>’」〖页面〗源码):

<a class="btn btn-primary" href="/Student/Add">Add</a>

跟我们想「‘<的>’」一样,「最后」asp-page被翻译成了href="/Student/Add"。

使用asp-route-xxx举行传参

〖页面〗间光导航还不够,更多「‘<的>’」时刻我们还需要举行〖页面〗间「‘<的>’」传参。{好比}我们「‘<的>’」更新按钮,需要跳转至Update〖页面〗而且通报一个id已往。

<a class="btn btn-primary" asp-page="Update" asp-route-id="@student.Id">Update</a>

我们使用asp-route-id来举行传参。(像)这里「‘<的>’」a「元素举行传参」,无非是放到url「‘<的>’」querystring〖上〗。让我们看一下天生「‘<的>’」html源码:

<a class="btn btn-primary" href="/Student/Update?id=2">Update</a>

不出所料「最后」id作为queryString被组装到了url〖上〗。
〖上〗面演示了Razor Pages「‘<的>’」导航跟传参,使用了几个框架内置「‘<的>’」属性,但实在我们基本可以不用这些器械就可以完成,使用尺度「‘<的>’」html方式来完成,{好比}删除按钮:

<a class="btn btn-danger" href="/student/delete?id=@student.Id" >Delete</a>

〖上〗面「‘<的>’」写法完全可以事情,而且加倍清晰明晰,谁看了都知道是啥意思。
小小「‘<的>’」吐槽下微软:(像)asp-page这种封装我是不太喜欢「‘<的>’」,“由于它掩盖了”html、http事情「‘<的>’」本质原理。这样会造成许多同砚知道使用asp-page怎么写,然则换个框架就不知道怎么搞了。我见过号称醒目asp.net「‘<的>’」同砚,然则对html、特别是对http一无所知。当你领会了真相后,甭管你用什么手艺,看起来实在都是一样「‘<的>’」,都是套路。

实现新增(student/add)〖页面〗

【新增〖页面〗】提供几个输入框输入学生信息,而且可以提交到后台。
《{“ 修改[”}》AddModel类:

   public class AddModel : PageModel
   {
       private readonly IStudentRepository _studentRepository;
       public AddModel(IStudentRepository studentRepository)
       {
           _studentRepository = studentRepository;
       }
       public void OnGet()
       {
       }

       [BindProperty]
       public Student Student { get; set; }

       public IActionResult OnPostSave()
       {
           _studentRepository.Add(Student);
           return RedirectToPage("List");
       }
   }

《{“ 修改[”}》Add.cshtml〖页面〗

@page
@model RazorPageCRUD.AddModel
@{
    ViewData["Title"] = "Add";
}

<h1>Add</h1>

<form method="post">
    <div class="form-group">
        <label>Id</label>
        <input type="number" asp-for="Student.Id" class="form-control" />
    </div>
    <div class="form-group">
        <label>Name</label>
        <input type="text" asp-for="Student.Name" class="form-control" />
    </div>
    <div class="form-group">
        <label>Age</label>
        <input type="number" asp-for="Student.Age" class="form-control" />
    </div>
    <div class="form-group">
        <label>Class</label>
        <input type="text" asp-for="Student.Class" class="form-control" />
    </div>
    <div class="form-group">
        <label>Sex</label>
        <input type="text" asp-for="Student.Sex" class="form-control" />
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary" asp-page-handler="Save">Save</button>
        <a asp-page="list" class="btn btn-dark">Cancel</a>
    </div>
</form>

Add〖页面〗使用一个form表单作为容器,内里「‘<的>’」文本框使用asp-for跟Model「‘<的>’」Student(属性确立联系)。
运行一下:

asp-for会把关联「‘<的>’」属性字段「‘<的>’」值作为input元素「‘<的>’」value「‘<的>’」值,会把关联「‘<的>’」属性名+字段「‘<的>’」名称作为input元素「‘<的>’」name属性「‘<的>’」值。看看天生「‘<的>’」html源码:

<input type="text" class="form-control" id="Student_Name" name="Student.Name" value="">

使用asp-page-handler来映射模子方式

我们「‘<的>’」Save是一次POST提交,显然我们需要一个后台方式来接受这次请求并处置它。使用asp-page-handler="Save"可以跟模子「‘<的>’」OnPostSave方式做映射。OnPost前缀示意对POST请求做响应,这又(有点(像))webapi。那么asp-page-handler为什么能映射模子「‘<的>’」方式呢?继续看看天生「‘<的>’」源码:

<button type="submit" class="btn btn-primary" formaction="/Student/Add?handler=Save">Save</button>

看到这里就明了了。「最后」天生「‘<的>’」button〖上〗有个formaction属性,值为/Student/Add?handler=Save。formaction相当于在form元素〖上〗指定action属性「‘<的>’」提交地址,而且在url〖上〗附带了一个参数handler=save,这样后台就能查找具体要执行哪个方式了。不外据我「‘<的>’」履历formaction{属性存在浏览器兼容}问题

使用BindPropertyAttribute举行参数绑定

光能映射后台方式还不够,我们还需要把前端「‘<的>’」数据提交到后台,而且拿到它。这里可以使用BindPropertyAttribute来自动完成提交「‘<的>’」表单数据跟模子属性之间「‘<的>’」映射。这样我们「‘<的>’」方式可以是无参「‘<的>’」方式。


        [BindProperty]
        public Student Student { get; set; }

看到这里突然有种MVVM模式「‘<的>’」既视感了。虽然不是实时「‘<的>’」双向绑定,然则也实现了简朴「‘<的>’」前后端绑定手艺。另外提一句既然我们前端「‘<的>’」数据是通过表单提交,那么跟mvc一样,使用FromFormAttribute实在一样可以举行参数绑定「‘<的>’」。

public IActionResult OnPostSave([FromForm] Stuend student)

这有获取表单数据毫无问题。

在后台方式举行〖页面〗导航

当保留乐成后需要使〖页面〗跳转到列表〖页面〗,可以使用RedirectToPage等方式举行跳转,OnPostSave方式「‘<的>’」返回值类型也改成IActionResult,这就异常mvc了,跟action方式一模一样「‘<的>’」套路。

public IActionResult OnPostSave()
        {
            _studentRepository.Add(Student);
            return RedirectToPage("List");
        }

《{“ 修改[”}》编辑(student/update)〖页面〗

《{“ 修改[”}》,删除〖页面〗就没什么很多多少讲「‘<的>’」了,使用前面「‘<的>’」知识点轻松就能实现。
《{“ 修改[”}》cshtml模板:

@page
@model RazorPageCRUD.UpdateModel
@{
    ViewData["Title"] = "Update";
}

<h1>Update</h1>

<form method="post">
    <div class="form-group">
        <label>Id</label>
        <input type="number" asp-for="Student.Id" class="form-control" />
    </div>
    <div class="form-group">
        <label>Name</label>
        <input type="text" asp-for="Student.Name" class="form-control" />
    </div>
    <div class="form-group">
        <label>Age</label>
        <input type="number" asp-for="Student.Age" class="form-control" />
    </div>
    <div class="form-group">
        <label>Class</label>
        <input type="text" asp-for="Student.Class" class="form-control" />
    </div>
    <div class="form-group">
        <label>Sex</label>
        <input type="text" asp-for="Student.Sex" class="form-control" />
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary" asp-page-handler="Edit">Save</button>
        <a asp-page="list" class="btn btn-dark">Cancel</a>
    </div>
</form>

《{“ 修改[”}》UpdateModel类:

    public class UpdateModel : PageModel
    {
        private readonly IStudentRepository _studentRepository;
        public UpdateModel(IStudentRepository studentRepository)
        {
            _studentRepository = studentRepository;
        }
        public void OnGet(int id)
        {
            Student = _studentRepository.Get(id);
        }

        [BindProperty]
        public Student Student { get; set; }

        public IActionResult OnPostEdit()
        {
            _studentRepository.Update(Student);

            return RedirectToPage("List");
        }
    }

运行一下:

《{“ 修改[”}》删除(student/delete)〖页面〗

删除〖页面〗跟前面一样没什么很多多少讲「‘<的>’」了,使用前面「‘<的>’」知识点轻松就能实现。
《{“ 修改[”}》Delete.cshtml模板:

@page
@model RazorPageCRUD.DeleteModel
@{
    ViewData["Title"] = "Delete";
}

<h1>Delete</h1>
<h2 class="text-danger">
    确定删除?
</h2>
<form method="post">
    <div class="form-group">
        Id: @Model.Student.Id
    </div>
    <div class="form-group">
        Name:@Model.Student.Name
    </div>
    <div class="form-group">
        Age: @Model.Student.Age
    </div>
    <div class="form-group">
        Class: @Model.Student.Class
    </div>
    <div class="form-group">
        Sex: @Model.Student.Sex
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary" asp-page-handler="Delete" asp-route-id="@Model.Student.Id">Delete</button>
        <a asp-page="list" class="btn btn-dark">Cancel</a>
    </div>
</form>

《{“ 修改[”}》DeleteModel类:

     public class DeleteModel : PageModel
    {
        private readonly IStudentRepository _studentRepository;
        public DeleteModel(IStudentRepository studentRepository)
        {
            _studentRepository = studentRepository;
        }

        public void OnGet(int id)
        {
            Student = _studentRepository.Get(id);
        }

        public Student Student { get; set; }

        public IActionResult OnPostDelete(int id)
        {
            _studentRepository.Delete(id);

            return RedirectToPage("list");
        }
    }  

运行一下:

总结

通过〖上〗「‘<的>’」简朴示例,对Razor Pages有了也许「‘<的>’」领会。Razor Pages本质〖上〗对MVC模式「‘<的>’」简化,后台模子聚合了Controller跟Model「‘<的>’」「‘<的>’」观点。而且提供了一些内置html属性实现绑定手艺。有人说Razor Pages是WebForm「‘<的>’」继任者,我倒不以为。小我私家以为它更(像)是MVC/MVVM「‘<的>’」一种夹杂。[BindProperty](有点(像))WPF里「‘<的>’」依赖属性,OnPostXXX方式就(像)是Command下令;又或者[BindProperty](像)VUE「‘<的>’」Data属性〖上〗「‘<的>’」字段,OnPostXXX(像)Methods里「‘<的>’」方式;又或者整个Model(像)极了angularjs「‘<的>’」$scope,夹杂了数据跟方式。只是Razor Pages毕竟是‘服务’端渲染,不能举行实时双向绑定而已。「最后」,说实话通过简朴「‘<的>’」体验,Razor Pages开发模式跟MVC模式相比并未有什么特殊「‘<的>’」优点,不知道后续发展会若何。

,

Sunbet

Sunbet www.xzsxzxx.cn是Sunbet娱乐「‘<的>’」官方网站,是亚洲唯一「‘<的>’」Sunbet。公司业务主要范围:Sunbet、Sunbet、sunbet娱乐等。

版权声明

本文仅代表作者观点,
不代表本站dafa888的立场。
本文系作者授权发表,未经许可,不得转载。

评论