通过 SignalR 类库,实现 ASP.NET MVC 的实时通信

来源:互联网 发布:冠趣网络 编辑:程序博客网 时间:2024/06/05 05:01

在本文中,您将学到在现有 ASP.NET MVC 框架的 CRUD 项目中,如何使用 SignalR 类库,显示来自数据库的实时更新。在这一主题中,我们将重点放在在现有 ASP.NET MVC 框架的 CRUD 项目中,如何使用 SignalR 类库,显示来自数据库的实时更新。 本文系国内 ITOM 管理平台 OneAPM 工程师编译整理。

本主题有以下两个步骤:

  1. 我们将创建一个示例应用程序来执行 CRUD 操作。

  2. 我们将使用 SignalR 类库让应用实时。

那些不熟悉 SignalR 的,请访问我以前有关 SignalR 概述 的文章。

第一步:

我们需要创建一个名为 CRUD_Sample 的数据库。在示例数据库中创建一个名为 Customer 的表。

CREATE TABLE [dbo].[Customer](    [Id] [bigint] IDENTITY(1,1)NOTNULL,    [CustName] [varchar](100)NULL,    [CustEmail] [varchar](150)NULL  ) 

存储过程

USE [CRUD_Sample]  GO  /****** Object:  StoredProcedure [dbo].[Delete_Customer]    Script Date: 12/27/2015 1:44:05 PM ******/  SETANSI_NULLSON  GO  SETQUOTED_IDENTIFIERON  GO  -- =============================================  -- Author:      <Author,,Name>  -- Create date: <Create Date,,>  -- Description: <Description,,>  -- =============================================  CREATE PROCEDURE [dbo].[Delete_Customer]      -- Add the parameters for the stored procedure here       @Id Bigint  AS  BEGIN      -- SET NOCOUNT ON added to prevent extra result sets from      -- interfering with SELECT statements.      SETNOCOUNTON;  -- Insert statements for procedure here      DELETE FROM [dbo].[Customers] WHERE [Id] = @Id      RETURN 1  END  GO  /****** Object:  StoredProcedure [dbo].[Get_Customer]    Script Date: 12/27/2015 1:44:05 PM ******/  SETANSI_NULLSON  GO  SETQUOTED_IDENTIFIERON  GO  -- =============================================  -- Author:      <Author,,Name>  -- Create date: <Create Date,,>  -- Description: <Description,,>  -- =============================================  CREATE PROCEDURE [dbo].[Get_Customer]       -- Add the parameters for the stored procedure here      @Count INT  AS  BEGIN      -- SET NOCOUNT ON added to prevent extra result sets from      -- interfering with SELECT statements.      SETNOCOUNTON;  -- Insert statements for procedure here      SELECT top(@Count)*FROM [dbo].[Customers]  END  GO  /****** Object:  StoredProcedure [dbo].[Get_CustomerbyID]    Script Date: 12/27/2015 1:44:05 PM ******/  SETANSI_NULLSON  GO  SETQUOTED_IDENTIFIERON  GO  -- =============================================  -- Author:      <Author,,Name>  -- Create date: <Create Date,,>  -- Description: <Description,,>  -- =============================================  CREATE PROCEDURE [dbo].[Get_CustomerbyID]       -- Add the parameters for the stored procedure here      @Id BIGINT  AS  BEGIN      -- SET NOCOUNT ON added to prevent extra result sets from      -- interfering with SELECT statements.      SETNOCOUNTON;  -- Insert statements for procedure here      SELECT*FROM [dbo].[Customers]      WHERE Id=@Id  END  GO  /****** Object:  StoredProcedure [dbo].[Set_Customer]    Script Date: 12/27/2015 1:44:05 PM ******/  SETANSI_NULLSON  GO  SETQUOTED_IDENTIFIERON  GO  -- =============================================  -- Author:      <Author,,Name>  -- Create date: <Create Date,,>  -- Description: <Description,,>  -- =============================================  CREATE PROCEDURE [dbo].[Set_Customer]      -- Add the parameters for the stored procedure here       @CustNameNvarchar(100)      ,@CustEmailNvarchar(150)  AS  BEGIN      -- SET NOCOUNT ON added to prevent extra result sets from      -- interfering with SELECT statements.      SETNOCOUNTON;  -- Insert statements for procedure here      INSERT INTO [dbo].[Customers]([CustName],[CustEmail])      VALUES(@CustName,@CustEmail)      RETURN 1  END  GO  /****** Object:  StoredProcedure [dbo].[Update_Customer]    Script Date: 12/27/2015 1:44:05 PM ******/  SETANSI_NULLSON  GO  SETQUOTED_IDENTIFIERON  GO  -- =============================================  -- Author:      <Author,,Name>  -- Create date: <Create Date,,>  -- Description: <Description,,>  -- =============================================  CREATE PROCEDURE [dbo].[Update_Customer]      -- Add the parameters for the stored procedure here       @Id Bigint      ,@CustNameNvarchar(100)      ,@CustEmailNvarchar(150)  AS  BEGIN      -- SET NOCOUNT ON added to prevent extra result sets from      -- interfering with SELECT statements.      SETNOCOUNTON;  -- Insert statements for procedure here      UPDATE [dbo].[Customers] SET[CustName] = @CustName,[CustEmail]= @CustEmail      WHERE [Id] = @Id      RETURN 1  END  GO  

启动 MVC 项目

创建示例应用程序,我们需要 Visual Studio 2012 或更高版本,并且该服务器平台必须支持 .NET 4.5。

步骤 1:

Getting Started with MVC

Step 2:

Web application

Step 3:

select template

点击 OK,Visual Studio 将会创建一个新的 ASP.NET 工程。

使用通用类库

使用通用功能,我们可以减少代码数量。

namespace WebApplication1.Repository  {      interfaceIRepository < T > : IDisposablewhereT: class      {          IEnumerable < T > ExecuteQuery(stringspQuery, object[] parameters);          TExecuteQuerySingle(stringspQuery, object[] parameters);          intExecuteCommand(stringspQuery, object[] parameters);      }  }  

接口 IRepository

显示一个通用类库的 T 型接口,它是 SQL 实体的 LINQ。它提供了一个基本的界面操作,如 Insert, Update, Delete, GetById and GetAll。

IDisposable

IDisposable接口提供了一种机制,释放非托管资源。

where T : class

这是制约泛型参数的一类。点击查看更多。

类型参数必须是引用类型;这也适用于任何类,接口,委托或数组类型。

namespace WebApplication1.Repository  {      public class GenericRepository < T > : IRepository < T > whereT: class      {          Customer_Entities context = null;          privateDbSet < T > entities = null;          public GenericRepository(Customer_Entities context)          {              this.context = context;              entities = context.Set < T > ();          }          ///<summary>          /// Get Data From Database          ///<para>Use it when to retive data through a stored procedure</para>          ///</summary>          public IEnumerable < T > ExecuteQuery(stringspQuery, object[] parameters)          {              using(context = newCustomer_Entities())              {                      returncontext.Database.SqlQuery < T > (spQuery, parameters).ToList();              }          }          ///<summary>          /// Get Single Data From Database          ///<para>Use it when to retive single data through a stored procedure</para>          ///</summary>          public TExecuteQuerySingle(stringspQuery, object[] parameters)          {              using(context = newCustomer_Entities())              {                  returncontext.Database.SqlQuery < T > (spQuery, parameters).FirstOrDefault();              }          }          ///<summary>          /// Insert/Update/Delete Data To Database          ///<para>Use it when to Insert/Update/Delete data through a stored procedure</para>          ///</summary>          public intExecuteCommand(stringspQuery, object[] parameters)          {              int result = 0;              try              {                  using(context = newCustomer_Entities())                  {                      result = context.Database.SqlQuery < int > (spQuery, parameters).FirstOrDefault();                  }              }              catch              {}              return result;          }          private bool disposed = false;          protected virtualvoid Dispose(bool disposing)          {              if (!this.disposed)              {                  if (disposing)                  {                      context.Dispose();                  }              }              this.disposed = true;          }          public void Dispose()          {              Dispose(true);              GC.SuppressFinalize(this);          }      }  } 

使用 middle-tire 结构

namespace WebApplication1.Services  {      public partial class CustomerService      {          privateGenericRepository < Customer > CustRepository;          //CustomerRepositoryCustRepository;          public CustomerService()          {              this.CustRepository = newGenericRepository < Customer > (newCustomer_Entities());          }          public IEnumerable < Customer > GetAll(object[] parameters)          {              stringspQuery = "[Get_Customer] {0}";              returnCustRepository.ExecuteQuery(spQuery, parameters);          }          public CustomerGetbyID(object[] parameters)          {              stringspQuery = "[Get_CustomerbyID] {0}";              returnCustRepository.ExecuteQuerySingle(spQuery, parameters);          }          public int Insert(object[] parameters)          {              stringspQuery = "[Set_Customer] {0}, {1}";              returnCustRepository.ExecuteCommand(spQuery, parameters);          }          public int Update(object[] parameters)          {              stringspQuery = "[Update_Customer] {0}, {1}, {2}";              returnCustRepository.ExecuteCommand(spQuery, parameters);          }          public int Delete(object[] parameters)          {              stringspQuery = "[Delete_Customer] {0}";              returnCustRepository.ExecuteCommand(spQuery, parameters);          }      }  }  

在 MVC 架构应用程序中使用通用库

namespace WebApplication1.Controllers  {      public class HomeController: Controller      {          private CustomerServiceobjCust;          //CustomerRepositoryCustRepository;          public HomeController()              {                  this.objCust = newCustomerService();              }              // GET: Home          public ActionResult Index()          {              int Count = 10;              object[] parameters = {                  Count              };              var test = objCust.GetAll(parameters);              return View(test);          }          public ActionResult Insert()          {              return View();          }          [HttpPost]          public ActionResult Insert(Customer model)          {              if (ModelState.IsValid)              {                  object[] parameters = {                      model.CustName,                      model.CustEmail                  };                  objCust.Insert(parameters);              }              return RedirectToAction("Index");          }          public ActionResult Delete(int id)          {              object[] parameters = {                  id              };              this.objCust.Delete(parameters);              return RedirectToAction("Index");          }          public ActionResult Update(int id)          {              object[] parameters = {                  id              };              return View(this.objCust.GetbyID(parameters));          }          [HttpPost]          public ActionResult Update(Customer model)          {              object[] parameters = {                  model.Id,                  model.CustName,                  model.CustEmail              };              objCust.Update(parameters);              return RedirectToAction("Index");          }          protected override void Dispose(bool disposing)          {              base.Dispose(disposing);          }      }  } 

在 MVC 架构应用程序中使用视图

Index

@model IList  <WebApplication1.Models.Customer>  @{  ViewBag.Title = "Index";  }      <linkhref="~/Content/bootstrap/css/bootstrap.min.css"rel="stylesheet"/>      <divclass="clearfix">       </div>      <divclass="clearfix">       </div>      <divclass="container">          <divclass="table-responsive">  @Html.ActionLink("New Customer", "Insert", "Home")              <tableclass="table table-bordered table-striped">                  <thead>                      <tr>                          <th>ID</th>                          <th>Name</th>                          <th>Email ID</th>                          <th>Delete</th>                          <th>Update</th>                      </tr>                  </thead>                  <tbody>                  @if (Model != null)                  {                      foreach (var item in Model)                      {                         <tr>                             <td>@item.Id</td>                             <td>@item.CustName</td>                             <td>@item.CustEmail</td>                             <td>@Html.ActionLink("Delete", "Delete", "Home", new { id = @item.Id }, null)</td>                             <td>@Html.ActionLink("Update", "Update", "Home", new { id = @item.Id }, null)</td>                         </tr>                      }                  }                  </tbody>              </table>          </div>          <divclass="clearfix">           </div>      </div> 

Insert

@model WebApplication1.Models.Customer  @{  ViewBag.Title = "Insert";  }  <link href="~/Content/bootstrap/css/bootstrap.min.css"rel="stylesheet"/>  <div class="clearfix">   </div>  <div class="clearfix">   </div>  <div class="container">      <div class="table-responsive col-md-6 col-md-offset-3">          <table class="table table-bordered table-striped">              <tbody>  @using (Html.BeginForm("Insert", "Home", FormMethod.Post))  {  @*                  <tr>                      <td class="col-md-4">ID</td>                      <td class="col-md-8">@Html.TextBoxFor(m =>m.Id)</td>                  </tr>*@                  <tr>                      <td class="col-md-4">Name                      </td>                      <td class="col-md-8">@Html.TextBoxFor(m =>m.CustName)                      </td>                  </tr>                  <tr>                      <td class="col-md-4">Email ID                      </td>                      <td class="col-md-8">@Html.TextBoxFor(m =>m.CustEmail)                      </td>                  </tr>                  <tr>                      <td class="text-right"colspan="2">                          <input type="submit"value="Save"class="btnbtn-primary"/>                      </td>                  </tr>  }              </tbody>          </table>      </div>      <div class="clearfix">       </div>  @Html.ActionLink("Home", "Index", "Home")  </div>  

Update

@model WebApplication1.Models.Customer  @{  ViewBag.Title = "Update";  }  <link href="~/Content/bootstrap/css/bootstrap.min.css"rel="stylesheet"/>  <div class="clearfix">   </div>  <div class="clearfix">   </div>  <div class="container">      <div class="table-responsive">          <table class="table table-bordered table-striped">              <thead>                  <tr>                      <th>Name</th>                      <th>Email ID</th>                      <th>Update</th>                  </tr>              </thead>              <tbody>                  <tr>  @using (Html.BeginForm("Update", "Home", FormMethod.Post))  {                      <td>@Html.TextBoxFor(m =>m.CustName)</td>                      <td>@Html.TextBoxFor(m =>m.CustEmail)</td>                      <td>                          <inputtype="submit"value="Update"class="btnbtn-primary"/>                      </td>  }                  </tr>              </tbody>          </table>      </div>  </div>  

步骤2:

启动 SignalR

第一件事是获得 NuGet 参照。

在 NuGet 上获得。

安装 Microsoft.AspNet.SignalR 包
Microsoft.AspNet.SignalR

注册 SignalR 中间件

安装后需要创建 OwinStartup 类。

下面的代码将一段简单中间件向 OWIN 管道,实现接收 Microsoft.Owin.IOwinContext 实例的功能。

当服务器收到一个 HTTP 请求,OWIN 管道调用中间件。中间件设置内容类型的响应和写响应体。

Startup.cs

using System;  using System.Threading.Tasks;  using Microsoft.Owin;  using Owin;  [assembly: OwinStartup(typeof (WebAppSignalR.Startup))]  namespace WebAppSignalR  {      public class Startup      {          public void Configuration(IAppBuilder app)          {              app.MapSignalR();          }      }  }  

创建使用 Hub 类

完成前面的过程之后,创建一个 Hub。一个SignalR Hub 让从服务器到客户端连接,并从客户端到服务器的远程过程调用(RPC)。

CustomerHub.cs

using System;  using System.Collections.Generic;  using System.Linq;  using System.Web;  using Microsoft.AspNet.SignalR;  using Microsoft.AspNet.SignalR.Hubs;  namespace WebApplication1.Hubs  {      public class CustomerHub: Hub      {          [HubMethodName("broadcastData")]          public static void BroadcastData()          {              IHubContext context = GlobalHost.ConnectionManager.GetHubContext < CustomerHub > ();              context.Clients.All.updatedData();          }      }  }  

代码说明

IHubContext context = GlobalHost.ConnectionManager.GetHubContext<CustomerHub>(); 

获得 CustomerHub context:

context.Clients.All.updatedData();  

它请求 SignalR 的客户端部分,并告诉它执行 JavaScript 的 updatedData()方法。

修改现有视图 Let’s Modify our Existing View

修改一部分索引视图,将通过局部视图显示数据。

Index

@model IList < WebApplication1.Models.Customer > @  {      ViewBag.Title = "Index";  } < linkhref = "~/Content/bootstrap/css/bootstrap.min.css"  rel = "stylesheet" / > < divclass = "clearfix" > & nbsp; < /div> < divclass = "clearfix" > & nbsp; < /div> < divclass = "container" > < divclass = "table-responsive" > @Html.ActionLink("New Customer", "Insert", "Home") < hr / > < divid = "dataTable" > < /div> < /div> < divclass = "clearfix" > & nbsp; < /div> < /div>  @section JavaScript  { < scriptsrc = "~/Scripts/jquery.signalR-2.2.0.min.js" > < /script> < scriptsrc = "/signalr/hubs" > < /script> < scripttype = "text/javascript" > $(function ()      {          // Reference the hub.          var hubNotif = $.connection.customerHub;          // Start the connection.          $.connection.hub.start().done(function ()          {              getAll();          });          // Notify while anyChanges.          hubNotif.client.updatedData = function ()          {              getAll();          };      });      function getAll()      {          var model = $('#dataTable');          $.ajax(          {              url: '/home/GetAllData',              contentType: 'application/html ; charset:utf-8',              type: 'GET',              dataType: 'html'          }).success(function (result)          {              model.empty().append(result);          }).error(function (e)          {              alert(e);          });      } < /script>  }  

局部视图

<table class="table table-bordered table-striped">      <thead>          <tr>              <th>ID</th>              <th>Name</th>              <th>Email ID</th>              <th>Delete</th>              <th>Update</th>          </tr>      </thead>      <tbody> @if (Model != null) { foreach (var item in Model) {          <tr>              <td>@item.Id</td>              <td>@item.CustName</td>              <td>@item.CustEmail</td>              <td>@Html.ActionLink("Delete", "Delete", "Home", new { id = @item.Id }, null)</td>              <td>@Html.ActionLink("Update", "Update", "Home", new { id = @item.Id }, null)</td>          </tr> } } </tbody>      </table> 

修改现有 Controller

主 Controller:

在主 Controller,我们将添加一个名为 GetAllDaTa()的方法。这是方法。

[HttpGet]  public ActionResult GetAllData()  {      int Count = 10;      object[] parameters = {          Count      };      var test = objCust.GetAll(parameters);      return PartialView("_DataList", test);  }  

在这里,返回局部视图返回的数据列表,且只返回空。

// GET: Home  public ActionResult Index()  {     return View();  }  

主 Controller

public class HomeController: Controller  {      private CustomerService objCust;      //CustomerRepositoryCustRepository;      public HomeController()      {          this.objCust = newCustomerService();      }      // GET: Home      public ActionResult Index()      {          return View();      }      [HttpGet]      public ActionResult GetAllData()      {          int Count = 10;          object[] parameters = {              Count          };          var test = objCust.GetAll(parameters);          return PartialView("_DataList", test);      }      public ActionResult Insert()      {          return View();      }      [HttpPost]      public ActionResult Insert(Customer model)      {          if (ModelState.IsValid)          {              object[] parameters = {                  model.CustName,                  model.CustEmail              };              objCust.Insert(parameters);          }          //Notify to all          CustomerHub.BroadcastData();          return RedirectToAction("Index");      }      public ActionResult Delete(int id)      {          object[] parameters = {              id          };          this.objCust.Delete(parameters);          //Notify to all          CustomerHub.BroadcastData();          return RedirectToAction("Index");      }      public ActionResult Update(int id)      {          object[] parameters = {              id          };          return View(this.objCust.GetbyID(parameters));      }      [HttpPost]      public ActionResult Update(Customer model)      {          object[] parameters = {              model.Id,              model.CustName,              model.CustEmail          };          objCust.Update(parameters);          //Notify to all          CustomerHub.BroadcastData();          returnRedirectToAction("Index");      }      protected override void Dispose(bool disposing)      {          base.Dispose(disposing);      }  }  

输出

output

希望能够帮助到您。

OneAPM 助您轻松锁定 .NET 应用性能瓶颈,通过强大的 Trace 记录逐层分析,直至锁定行级问题代码。以用户角度展示系统响应速度,以地域和浏览器维度统计用户使用情况。想阅读更多技术文章,请访问 OneAPM 官方博客。
本文转自 OneAPM 官方博客

原文地址: http://www.c-sharpcorner.com/UploadFile/302f8f/Asp-Net-mvc-real-time-app-with-signalr/

0 0
原创粉丝点击