在本文中,您将学到在现有 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:

Step 2:

Step 3:

点击 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);
}
}

输出

希望能够帮助到您。

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

本文转自 OneAPM 官方博客

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

通过 SignalR 类库,实现 ASP.NET MVC 的实时通信的更多相关文章

  1. ASP.NET MVC+Knockout+Web API+SignalR

    架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 2014-01-16 18: ...

  2. Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)

    简介       ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端 ...

  3. AngularJS+ASP.NET MVC+SignalR实现消息推送

    原文:AngularJS+ASP.NET MVC+SignalR实现消息推送 背景 OA管理系统中,员工提交申请单,消息实时通知到相关人员及时进行审批,审批之后将结果推送给用户. 技术选择 最开始发现 ...

  4. SignalR在ASP.NET MVC中的应用

    一.简介 ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得 ...

  5. Asp.NET websocket,Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)

    ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及 ...

  6. Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)

    简单介绍 关于SignalR的简单实用 请参考 Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室) 在上一篇中,我们只是介绍了简单的消息推送,今天我们来修改一下,实现 ...

  7. asp.net MVC SignalR 与数据库 实时同步显示

    asp.net MVC SignalR 与数据库 实时同步显示 错误:未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持.如果希望使用通知,请为此数据库启用 ...

  8. ASP.NET MVC中将控制器分离到类库的实现

    前言 在ASP.NET MVC的开发中,我们创建完项目之后,ASP.NET MVC是已Model-Controller-View的形式存在的,在创建项目自动生成的内容上Model我们很容易分离成类库, ...

  9. ASP.NET MVC SignalR(1):背景

    系列目录:ASP.NET MVC SignalR 关键词:HTTP.轮询.WebSocket.Server-Sent Events.长轮询.forever frame. 1. HTTP HTTP(Hy ...

随机推荐

  1. 基于Selenium2+Java的UI自动化(3) - 页面元素定位

    一.几种网页定位方式 webdriver的页面定位很灵活,提供了8种定位方式: 其中,常见的有三种:id .cssSelector .xpath: 一个元素如果存在 id 属性,则这个 id 的值,在 ...

  2. latch和DFF的区别和联系

    1.latch的缺点 ①没有时钟端,不受系统同步时钟的控制,无法实现同步操作:和当前我们尽可能采用时序电路的设计思路不符. ②对输入电平敏感,受布线延迟影响较大,很难保证输出没有毛刺产生: ③latc ...

  3. PHP生成HTML页面顶部出现空白部分(&#65279字符?)

    参考了:PHP生成HTML页面顶部出现空白部分(#65279字符?)的解决办法 查看拼接两个Html,查看文件格式是否是UTF-8 无Bom,我的内容Html是UTF-8 + Bom.

  4. HTTPS协议学习总结

    目录 一:什么是HTTPS协议?二:客户端与服务端如何建立HTTPS协议连接?三:证书.加密协议.信息摘要.签名算法概念解释与关系梳理四:低版本操作系统作为客户端发送HTTPS失败分析五:参考资料   ...

  5. (转载)研究openvswitch的流量模式

    最近又开始弄openvswitch,网上也有不少的资料,但是发觉都集中在openvswitch安装及简单使用或者一些原码分析,从心里来讲,感觉这些和心里得到的差距有点大啊,其实更希望能类似资料在ope ...

  6. orcale授权

    grant connect,resource,dba to 表名;--用户授权 CONNECT角色: --是授予最终用户的典型权利,最基本的 CREATE SESSION --建立会话 RESOURC ...

  7. UML 结构图之类图 总结

    [注] 本文不是类图的基础教程, 只是类图的图形总结. 学习UML图形 推荐阅读<UML参考手册>第2版. http://www.umlchina.com/ 推荐微软的开发软件设计模型 h ...

  8. 第一章 认识jQuery

    jQuery是一个优秀的JavaScript库,它凭借简洁地语法和跨平台的兼容性,极大地简化了开发人员遍历HTML文档,操作DOM,处理事件,执行动画和开发Ajax操作. jQuery优势:1.轻量级 ...

  9. Android Studio如何显示行号

    Android Studio默认没有显示行号,很多同学在使用中很不习惯.本经验介绍怎样让Android Studio显示行号. 首先我们打开我们下载安装好的Android Studio 然后右击工具按 ...

  10. Docker Machine, Compose, and Swarm: How They Work Together

    The three tools are now neatly packaged into what’s called the Docker Toolbox. Docker Machine1/ crea ...