65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ASP.NET MVC 和 jQuery 实现单页应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (3投票s)

2018年6月10日

CPOL

2分钟阅读

viewsIcon

27377

downloadIcon

55

在本文中,我将向您解释如何使用 asp.net mvc、jquery 和 sammy.js 实现单页应用程序。

引言

在本文中,我将告诉您如何使用 ASP.NET MVC 和 jQuery 创建单页应用程序。 在不使用 Angular、React 和其他第三方 JavaScript 的情况下,实现 SPA 比较困难。 在本文中,我将仅解释控制器和 UI 级别的交互。 我跳过了数据访问层。 如果您需要,请下载附件,其中包含应用程序的完整代码。

注意 - 我使用了代码优先方法进行 CRUD 操作。 下载项目文件后,请还原程序包,更改 web.config 中的连接字符串,并在包管理器控制台中运行 update-database 命令。

背景

所需内容

  • ASP.NET MVC
  • JQUERY
  • Sammy.JS(用于路由)

使用代码

创建一个新的 MVC 项目。

将 jQuery 和 Sammy.js 引用添加到您的布局页面。 添加 div 标签 (MainContent),我们将在其中渲染所有部分视图。

<head>  
    <meta charset="utf-8" />  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>@ViewBag.Title - My ASP.NET Application</title>  
    @Styles.Render("~/Content/css")  
    @Scripts.Render("~/bundles/modernizr")  
    <script src="~/Scripts/jquery-1.10.2.js"></script>  
    <script src="~/Scripts/sammy-0.7.4.js"></script>  
</head>  

在您的项目中创建 layout-routing.js 文件,其中包含您的应用程序路由结构,如下所示。

var mainContent;  
var titleContent;  
  
$(function () {  
    mainContent = $("#MainContent"); /// render partial views.  
    titleContent = $("title"); // render titles.  
});  
  
var routingApp = $.sammy("#MainContent", function () {  
    this.get("#/Student/Index", function (context) {  
        titleContent.html("Student Page");  
        $.get("/Student/Index", function (data) {  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Student/Add", function (context) {  
        titleContent.html("Add Student");  
        //$("#BigLoader").modal('show'); // If you want to show loader  
        $.get("/Student/Add", function (data) {  
            //$("#BigLoader").modal('hide');  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Student/Edit", function (context) {  
        titleContent.html("Edit Student");  
        $.get("/Student/Edit", {  
            studentID: context.params.id // pass student id  
        }, function (data) {  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Home/About", function (context) {  
        titleContent.html("About");  
        $.get("/Home/About", function (data) {  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Home/Contact", function (context) {  
        titleContent.html("Contact");  
        $.get("/Home/Contact", function (data) {  
            context.$element().html(data);  
        });  
    });  
});  
  
$(function () {  
    routingApp.run("#/Student/Index"); // default routing page.  
});  
  
function IfLinkNotExist(type, path) {  
    if (!(type != null && path != null))  
        return false;  
  
    var isExist = true;  
  
    if (type.toLowerCase() == "get") {  
        if (routingApp.routes.get != undefined) {  
            $.map(routingApp.routes.get, function (item) {  
                if (item.path.toString().replace("/#", "#").replace(/\\/g, '').replace("$/", "").indexOf(path) >= 0) {  
                    isExist = false;  
                }  
            });  
        }  
    } else if (type.toLowerCase() == "post") {  
        if (routingApp.routes.post != undefined) {  
            $.map(routingApp.routes.post, function (item) {  
                if (item.path.toString().replace("/#", "#").replace(/\\/g, '').replace("$/", "").indexOf(path) >= 0) {  
                    isExist = false;  
                }  
            });  
        }  
    }  
    return isExist;  
}  

IfLinkNotExist() 检查 URL 是否不应重复,之后我们将动态 URL 添加到页面加载时的路由列表中。

在 _layout.cshtml 页面中添加 layout-routing 引用。

<script src="~/layout-routing.js"></script>  
    @*@Scripts.Render("~/bundles/jquery")*@  
    @Scripts.Render("~/bundles/bootstrap")  
    @RenderSection("scripts", required: false)  

添加一个新的控制器 ‘WelcomeController’,该控制器只有一个操作 ‘Index’。

namespace MvcSpaDemo.Controllers  
{  
    public class WelcomeController : Controller  
    {  
        public ActionResult Index()  
        {  
            return View();  
        }  
    }  
}

使用右键单击创建 ‘Index’ 操作的视图。

在该视图中,附加布局页面链接。(我们需要第一次渲染布局页面)。

@{  
    ViewBag.Title = "Index";  
    Layout = "~/Views/Shared/_Layout.cshtml";  
}  
  
<h1>Welcome</h1>  

现在,创建 Student Controller,其中包含 Student CRUD 操作模块(添加、更新、删除、查看)。

查看学生

public ActionResult Index()  
 {  
     return PartialView();  
 }  
  
 public ActionResult _Index()  
 {  
     var students = StudentData.GetStudents();  
     return PartialView(students);  
  } 

添加两个没有布局页面的视图。 一个用于外部学生内容,如标题、添加按钮等,另一个用于学生表格。

Index.cshtml 

@{  
    Layout = null;  
}  
  
<h4>Students</h4>  
  
<div class="row">  
    <a href="#/Student/Add">Add Student</a>  
</div>  
  
<div class="row">  
    <div id="StudentDiv">  
    </div>  
</div>  
  
<script>  
    $(function () {  
        GetStudents();  
    });  
  
    function GetStudents() {  
        $.get("/Student/_Index/", function (data) {  
            $("#StudentDiv").html(data);  
        });  
    }  
  
    function DeleteStudent(studentID) {  
        if (confirm("Delete student?")) {  
            $.get("/Student/Delete/", { studentID: studentID }, function (data) {  
                GetStudents();  
            });  
        }  
    }  
</script>  

_Index.cshtml

@model IEnumerable<MvcSpaDemo.Entities.Student>  
@{  
    Layout = null;  
}  
  
<table class="table table-striped table-bordered">  
    <thead>  
        <tr>  
            <th>ID</th>  
            <th>Name</th>  
            <th>Email</th>  
            <th>Class</th>  
            <th>Action</th>  
        </tr>  
    </thead>  
    <tbody>  
        @foreach (var item in Model)  
        {  
            <tr>  
                <td>@item.StudentID</td>  
                <td>@item.FirstName @item.LastName</td>  
                <td>@item.Email</td>  
                <td>@item.Class</td>  
                <td>  
                    <a href="#/Student/Edit?id=@item.StudentID">Edit</a>  
                    <a href="javascript::;" onclick="DeleteStudent('@item.StudentID')">Delete</a>  
                </td>  
            </tr>  
        }  
    </tbody>  
</table>  

更改 RouteConfig.cs 中的默认控制器和操作。

public class RouteConfig  
    {  
        public static void RegisterRoutes(RouteCollection routes)  
        {  
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  
            routes.MapRoute(  
                name: "Default",  
                url: "{controller}/{action}/{id}",  
                defaults: new { controller = "Welcome", action = "Index", id = UrlParameter.Optional }  
            );  
        }  
    }  

使用 F5 运行应用程序。 同样为 About 和 Contact 页面执行相同的路由。

添加学生 asd 

现在,在 Controller 中添加“创建学生操作”。

public ActionResult Add()  
        {  
            var student = new Student();  
            ViewBag.Status = "Add";  
            return PartialView(student);  
        }  
  
        [HttpPost]  
        public ActionResult Create(Student student)  
        {  
            StudentData.AddStudent(student);  
            return Json(true, JsonRequestBehavior.AllowGet);  
        }  

我们将添加带有动态路由脚本的添加页面,用于创建或更新。

@model MvcSpaDemo.Entities.Student  
@{  
    ViewBag.Title = "Add";  
    Layout = null;  
  
    // We use same page for add and edit.  
    var urlPostString = "/Student/Create";  
    if (ViewBag.Status == "Edit")  
    {  
        urlPostString = "/Student/Update";  
    }  
}  
  
<h2>@ViewBag.Status Student</h2>  
  
<form id="frmStudent" name="frmStudent" method="post" action="#@urlPostString">  
    @Html.HiddenFor(x => x.StudentID)  
    <div class="row">  
        <div class="form-group">  
            <label for="Variables">First Name</label>  
            @Html.TextBoxFor(x => x.FirstName, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <label for="Variables">Last Name</label>  
            @Html.TextBoxFor(x => x.LastName, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <label for="Variables">Email</label>  
            @Html.TextBoxFor(x => x.Email, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <label for="Variables">Class</label>  
            @Html.TextBoxFor(x => x.Class, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <input type="submit" class="btn btn-primary" value="Submit" />  
        </div>  
    </div>  
</form>  
  
<script>  
    $("#frmStudent").on("submit", function (e) {  
        debugger;  
        //if ($("#frmStudent").valid()) {  
        routingApp.runRoute('post', '#@urlPostString');  
        e.preventDefault();  
        e.stopPropagation();  
        //}  
    });  
  
    // add dynamic create or update link  
  
    debugger;  
    if (IfLinkNotExist("POST", "#@urlPostString")) {  
        routingApp.post("#@urlPostString", function (context) {  
            //$("#BigLoader").modal('show');  
            var formData = new FormData($('#frmStudent')[0]);  
            $.ajax({  
                url: '@urlPostString',  
                data: formData,  
                type: "POST",  
                contentType: false,  
                processData: false,  
                success: function (data) {  
                    //$("#BigLoader").modal('hide');  
                    if (data) {  
                        if ('@ViewBag.Status' == 'Add')  
                            alert("Student successfully added");  
                        else if ('@ViewBag.Status' == 'Edit')  
                            alert("Student successfully updated");  
                        window.location.href = "#/Student/Index";  
                    }  
                    else {  
                        alert('Something went wrong');  
                    }  
                },  
                error: function () {  
                    alert('Something went wrong');  
                }  
            });  
        });  
    }  
  
</script>  

现在,运行应用程序。

编辑学生

现在,进入编辑模块。 在 Controller 中添加编辑操作。

public ActionResult Edit(int studentID) // studentID nothing but parameter name which we pass in layout-routing.  
        {  
            var student = StudentData.GetStudentById(studentID);  
            ViewBag.Status = "Edit";  
            return PartialView("Add", student);  
        }  
  
        [HttpPost]  
        public ActionResult Update(Student student)  
        {  
            StudentData.UpdateStudent(student);  
            return Json(true, JsonRequestBehavior.AllowGet);  
        }  

我们为添加和编辑使用了相同的部分视图,因此无需为编辑创建新的视图。

添加操作方法后,只需运行应用程序即可。

删除学生 

现在,我们将实现删除操作。

我们已经在 Student Index.cshtml 中编写了删除按钮的代码。

function GetStudents() {  
        $.get("/Student/_Index/", function (data) {  
            $("#StudentDiv").html(data);  
        });  
    }  
  
    function DeleteStudent(studentID) {  
        if (confirm("Delete student?")) {  
            $.get("/Student/Delete/", { studentID: studentID }, function (data) {  
                GetStudents();  
            });  
        }  
    }  

运行应用程序。

我希望您喜欢这篇文章。 欢迎您对本文提出宝贵的反馈、问题或评论。

© . All rights reserved.