手游如何实现热更新 signalr 是怎么实现的

&&&&&&&&&&&&&&&&&&&&&&&&& 16:14:52
&&网站联系: qq: email:&瞬间让SignalR 实现在线聊天室~ - 推酷
瞬间让SignalR 实现在线聊天室~
ASP.NET &SignalR &是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时 服务器代码可以立即向其推送内容 ,而不是让服务器等待客户端请求新的数据。
直接看效果图:
实现过程如下:
新建一个 Hub 类
完整代码:
using Microsoft.O
[assembly: OwinStartupAttribute(typeof(Net.Ulon.SignalR.Startup))]
namespace Net.Ulon.SignalR
public partial class Startup
public void Configuration(IAppBuilder app)
app.MapSignalR();
using System.Collections.G
using System.L
using System.W
using Microsoft.AspNet.SignalR;
using System.Threading.T
using System.T
using Microsoft.AspNet.SignalR.H
namespace Net.Ulon.SignalR.Hub
/// &summary&
/// HubName不填写即为类名称
/// &/summary&
[HubName(&Chat&)]
public class ChatHub : Microsoft.AspNet.SignalR.Hub
/// &summary&
/// 获取当前客户端ID
/// &/summary&
public string _clientID { get { return Context.ConnectionId; } }
/// &summary&
/// 获取当前时间
/// &/summary&
private string _now { get { return DateTime.Now.ToString(&yyyy-MM-dd HH:mm:ss fff&); } }
/// &summary&
/// 获取消息
/// &/summary&
private string GetMsg(string msg)
return string.Format(&{0} : {1}&, _now, msg);
/// &summary&
/// 获取喊话
/// &/summary&
private string GetSay(string say)
return string.Format(&{0} :【{1}】 {2}&, _now, _clientID, say);
public void Send(string msg)
//发送消息给其他客户端
Clients.All.onMsg(_clientID, this.GetSay(msg));
//发送消息给当前客户端
Clients.Caller.onMsg(_clientID, this.GetMsg(&消息发送成功~&));
//Clients.Client(_clientID).onMsg(id, &Client Connect&);
/// &summary&
/// &/summary&
/// &returns&&/returns&
public override Task OnConnected()
Clients.Caller.onMsg(_clientID, this.GetMsg(&连接服务器~&));
Clients.AllExcept(_clientID).onMsg(_clientID, this.GetSay(&闪耀登场~&));
return base.OnConnected();
/// &summary&
/// &/summary&
/// &returns&&/returns&
public override Task OnDisconnected(bool stopCalled)
Clients.Caller.onMsg(_clientID, this.GetMsg(&连接断开~&));
Clients.AllExcept(_clientID).onMsg(_clientID, this.GetSay(&潇洒离去~&));
return base.OnDisconnected(stopCalled);
/// &summary&
/// 重新连接
/// &/summary&
/// &returns&&/returns&
public override Task OnReconnected()
Clients.Caller.onMsg(_clientID, this.GetMsg(&重新连接服务器~&));
Clients.AllExcept(_clientID).onMsg(_clientID, this.GetSay(&重出江湖~&));
return base.OnReconnected();
ViewBag.Title = &Home Page&;
@section scripts{
&script src=&~/Scripts/jquery-1.10.2.min.js&&&/script&
&script src=&/Scripts/jquery.signalR-2.2.0.min.js&&&/script&
&script src=&~/signalr/hubs&&&/script&
&script type=&text/javascript&&
$(function () {
var chat = $.connection.C
registerClientMethods(chat);
$.connection.hub.start().done(function () {
registerEvents(chat);
//注册客户端事件
function registerEvents(chat) {
$(&#send&).click(function () {
chat.server.send($(&#msg&).val());
//注册客户端方法
function registerClientMethods(chat) {
chat.client.onMsg = function (id, text) {
$(&#record&).append(&&div&& + text + &&/div&&);
&div&hello world~&/div&
&input type=&text& id=&msg& /&
&input type=&button& id=&send& value=&发送消息& /&
&div id=&record&&&/div&
主要的功能就是& 服务端推送消息 / 客户端发送消息
服务端推送消息
onMsg 是自定义的消息方法(客户端JS):
chat.client.onMsg = function (id, text) {
$(&#record&).append(&&div&& + text + &&/div&&);
1.发送给所有客户端
Clients.All.onMsg
2.发送给单一客户端
Clients.Client(_clientID).onMsg&&
3.发送给其他客户端
Clients.AllExcept(_clientID).onMsg
Clients.Ohther.onMsg
4.发送给当前客户端
Clients.Caller.onMsg
除了上面的单一的还有 Group 和 User
客户端发送消息
$(&#send&).click(function () {
chat.server.send($(&#msg&).val());
客户端发送下到服务端就是通过调用server,其中send是服务端定义的方法:
public void Send(string msg)
//发送消息给其他客户端
Clients.All.onMsg(_clientID, this.GetSay(msg));
//发送消息给当前客户端
Clients.Caller.onMsg(_clientID, this.GetMsg(&消息发送成功~&));
//Clients.Client(_clientID).onMsg(id, &Client Connect&);
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致常见的Web实时消息交互方式和SignalR
1. Web消息交互技术
1.1 常见技术
1.2 WebSocket介绍
1.3 WebSocket示例 2. Signal
2.1 SignalR是什么
2.2 默认传输方式
2.3 指定传输方式
2.4 自动管理传输方式
2.5 通信模型
2.6 SignalR示例(永久连接和Hubs(略))
(1)安装Nuget包
(2)增加SignalR服务
(3)增加Startup启动类
(3)前端js配置
(4)实际效果
(5).Net Client实现 3. 总结 4. 参考资料
最近因为项目中涉及到了实时数据的传输,特地去了解了一下当前Web应用中常见的实时交互手段,当然一开始也不仅限于Web客户端。从c#自带的Socket类,到Html5中的WebSocket,再到Asp .Net利器SignalR,总算将这块知识点及应用入门了,当然今天的主要内容还是Web端的消息交互技术(Ajax,Comet,WebSocket等),这些技术难度有中有低,应用场所也有不同,最后我们要根据项目情况来选择恰当的技术。接下来便简单介绍一下
1. Web消息交互技术
1.1 常见技术
应用技术 说明 优缺点 轮询(polling) 这应该是最常见的一种实现数据交互的方式,开发人员控制客户端以一定时间间隔中向服务器发送Ajax查询请求大,但是也因此,当服务器端内容并没有显著变化时,这种连接方式将带来很多无效的请求,造成服务器资源损耗。适合并发量小,实时性要求低的应用模型,更像是定时任务。 优点:实现最为简单,配置简单,出错几率小
缺点:每次都是一次完整的http请求,易延迟,有效请求命中率少,并发较大时,服务器资源损耗大 长轮询(long polling) 长轮询是对轮询的改进,客户端通过请求连接到服务器,并保持一段时间的连接状态,直到消息更新或超时才返回Response并中止连接,可以有效减少无效请求的次数。属于Comet实现 优点:有效减少无效连接,实时性较高
缺点:客户端和服务器端保持连接造成资源浪费,服务器端信息更新频繁时,long polling并不比polling高效,并且当数据量很大时,会造成连续的polls不断产生,性能上反而更糟糕 iframe流 iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长链接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。属于Comet实现 优点:实时性高,浏览器兼容度好
缺点:客户端和服务器端保持长连接造成资源浪费 WebSocket WebSocket是HTML5提供的一种在单个 TCP 连接上进行全双工通讯的协议,目前chrome、Firefox、Opera、Safari等主流版本均支持,Internet Explorer从10开始支持。另外因为WebSocket 提供浏览器一个原生的 socket实现,所以直接解Q了 Comet 架构很容易出错的问题,而在整架构的复杂度上也比传统的实现简单得多。 优点:服务器与客户端之间交换的数据包档头很小,节约带宽。全双工通信,服务器可以主动传送数据给客户端。
缺点:旧版浏览器不支持
Tips:浏览器和客户端之间想要进行WebSocket通信的话,从一开始的握手阶段,就要从HTTP协议升级为WebSocket协议,这是服务器根据WebSocket发送的请求包决定的。关于WebSocket的具体介绍(规范和语法和状态转换)可以参考使用 HTML5 WebSocket 构建实时 Web 应用.
1.2 WebSocket介绍
WebSocket本质上是一个基于TCP的持久化协议,相对于HTTP这种非持久的协议来说,它能够更好的节省服务器资源和带宽,并且真正实现实时通信。以下是它与传统技术的性能对比图(Websocket.org提供)
我们可以看到相比于传统技术,在流量和负载逐渐增大时,WebSocket的性能表现是远远超过它们的。
上文提到WebSocket在实际运用时是在握手阶段从http请求升级上来的,让我们来看一个Websocket请求的例子&&这里借用下维基百科的内容
1.客户端到服务器端
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Origin: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
2.服务器端到客户端
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws:///
注意&1.&中的UpGrade:websocket和Connection: Upgrade这两个核心属性表示本次是一个特殊的http请求,目的就是要将浏览器端和服务器端的通讯协议从HTTP协议&升级&&WebSocket协议,其他属性都是客户端向服务器端提供的握手信息。
Sec-WebSocket-Version: 13代表这是13版修订协议,Sec-WebSocket-Key是随机生成的,服务器端会把Sec-WebSocket-Key加上一个魔幻字符串&258EAFA5-E914-47DA-95CA-C5AB0DC85B11&。使用SHA-1加密,之后进行BASE-64编码,将结果做为Sec-WebSocket-Accept头的值,返回给客户端,表明服务器端同意创建Websocket请求。
1.3 WebSocket示例
以下用控制台和WebSocket简单实现下服务器和客户端的全双工通信,其中后台使用了SuperWebSocket技术
后台示例代码:
using SuperSocket.SocketB
using SuperWebS
using static System.C
namespace SuperWebSocketDemo
class Program
private static void Main(string[] args)
var server = new WebSocketServer();
server.NewSessionConnected += ServerNewSessionC
server.NewMessageReceived += ServerNewMessageR
server.SessionClosed += ServerSessionC
server.Setup(&127.0.0.1&, 4141);
server.Start();
catch (Exception ex)
WriteLine(ex.Message);
ReadKey();
private static void ServerSessionClosed(WebSocketSession session, CloseReason value)
WriteLine(session.Origin);
public static void ServerNewMessageRecevied(WebSocketSession session, string value)
WriteLine(value);
session.Send(&已收到:&+value);
public static void ServerNewSessionConnected(WebSocketSession session)
WriteLine(session.Origin);
前台示例代码,通过websocket的api我们可以很容易实现主要逻辑
最终结果如下图:
关于Web实时技术和WebSocket的介绍便到这里了,我们甚至可以用c#自己实现一个WebSocket的服务器,详情请看《如何编写一个WebSocket服务器》以及用c#实现的一个简单的WebSocket服务器《C# socket编程实践》,当然还是推荐SuperWebSocket。当然这篇只是简单的介绍而已,我自己的WebSocket实现(结合规范实现)也会在之后的博客中贴出。
假如还写得动&&
至此,数种常见的Web实时交互技术已经总览一遍了,对于Asp Web开发者来说,.Net平台为我们提供了一种简洁高效智能的实时信息交互技术&&SignalR,它集成了上述数种技术,并能根据配置自动或者手动选择最佳应用。
2.1 SignalR是什么
SignalR是一个.Net开源库,用于构建需要实时进行用户交互和数据更新的Web应用,如在线聊天,游戏,天气或者股票信息更新等实时应用程序。SignalR简化了构建实时应用的过程,它包括了一个Asp .Net服务器端库和一个Js端库,集成了数种常见的消息传输方式,如long polling,WebSocket,并提供相应的Api供开发人员选择如何调用,帮助其可以简单快速地实现客户端与服务器端相互间的实时通信。
当环境条件合适时,SignalR将WebSocket作为底层传输方式的优先实现,当然,它也能很高效地回退到其他技术。同时,SignalR提供了非常良好的Api以供远程调用(RPC) 浏览器中的js代码。
接下来,看看SignalR的传输方式和通信模型,这是SignalR的核心所在。
SignalR基本适用于任何可以用上述技术实现的场合,但是对寄宿平台版本有要求。如.Net Framework 平台,SignalR库需要4.5及以上版本的支持,而Mono上也实现了SignalR。如果是最新的.Net Core 1.0,建议大家直接使用SelfHost方式寄宿。
2.2 默认传输方式
传输方式 选择条件 long polling 1.IE8或更早版本
2.连接启动时JSONP参数设置为TRUE
3.Forever Frame不可用
WebSocket 1.正在使用跨域连接,并且符合以下条件(以下不满足任一条则使用长轮询)
(1).客户端支持CORS
(2).客户端支持WebSocket
(3).服务器端支持WebSocket
2.不配置使用JSONP,连接不跨域并且客户端和服务器端都支持WebSocket
(1).客户端支持CORS
(2).客户端支持WebSocket
(3).服务器端支持WebSocket
ServerSendEvent 客户端或服务器端不支持Websocket Forever Frame EventSource不可用(基本上除了IE外都支持)
2.3 指定传输方式
如果开发人员想要让客户端按照特定的方式和顺序进行数据传输,可以通过使用$.connection.start({transport:['webSockets','foeverFrame',&&]}),当客户端和服务器端并不支持指定方式时,程序将按照默认规则匹配传输方式。
用于指定传输方式的字符串常量定义如下:
webSockets foeverFrame serverSentEvents longPolling
2.4 自动管理传输方式
不指定传输方式时,SignalR会以Http方式发起请求,比对客户端和服务器端后,假如WebSocket可用,则自动升级到WebSocket模式,WebSocket是最理想的传输方式,除了能高效使用服务器内存,低延迟,还能实现客户端和服务器端的全双工通信。开发人员可以通过SignalR中js库的$.connection.chatHub.logging =来启用hub事件的日志记录
2.5 通信模型
SignalR包括两种客户端和服务器端之间进行通信的模型,Persistent Connections和Hubs。
通信模型 说明 Persistent Connections Persistent Connections表示一个发送单个,编组,广播信息的简单终结点。开发人员通过使用持久性连接Api,直接访问SignalR公开的底层通信协议。 Hubs Hubs是基于连接Api的更高级别的通信管道,它允许客户端和服务器上彼此直接调用方法,SignalR能够很神奇地处理跨机器的调度,使得客户端和服务器端能够轻松调用在对方端上的方法。使用Hub还允许开发人员将强类型的参数传递给方法并且绑定模型
2.6 SignalR示例(永久连接和Hubs(略))
Hubs的示例网上已经很多了(文章末尾附上链接),这边先来快速开始一个SignalR使用永久连接的Demo.
关于永久连接和Hubs的区别,这里有些很棒的解释.
(1)安装Nuget包
创建一个默认的Asp .Net Mvc项目
使用Install-Package Microsoft.AspNet.SignalR安装SignalR包
(2)增加SignalR服务
新增Connections文件夹,添加SignalR永久连接类ChatConnections
using System.Threading.T
using Microsoft.AspNet.SignalR;
namespace SignalRUsingPersistentConnectionsDemo.Connections
public class ChatConnection : PersistentConnection
protected override Task OnConnected(IRequest request, string connectionId)
return Connection.Send(connectionId, &Welcome!&);
protected override Task OnReceived(IRequest request, string connectionId, string data)
return Connection.Broadcast(data);
(3)增加Startup启动类
using Microsoft.O
using SignalRUsingPersistentConnectionsD
using SignalRUsingPersistentConnectionsDemo.C
[assembly: OwinStartup(typeof (Startup))]
namespace SignalRUsingPersistentConnectionsDemo
public class Startup
public void Configuration(IAppBuilder app)
// 有关如何配置应用程序的详细信息,请访问 /fwlink/?LinkID=316888
// 配置上文实现的ChatConnections
app.MapSignalR(&/Connections/ChatConnection&);
(4)前端js配置
前端js实现消息广播,并实时记录
(5)实际效果
(6).Net Client实现
除了Web实时应用之外,你也可以用其他应用程序实现实时交互,如控制台。只需要Install-Package Microsoft.AspNet.SignalR.Client命令,示例编码如下
using Microsoft.AspNet.SignalR.C
using static System.C
namespace DotnetClientWithSignalRDemo
internal class Program
private static void Main(string[] args)
var connection = new Connection(&http://localhost:1508/Connections/ChatConnection&);
connection.Received += WriteL
connection.Start().Wait();
while ((line = ReadLine()) != null)
connection.Send(line).Wait();
效果如图,同样实现了双向通信
至此,常见的Web实时交互技术和SignalR简单介绍就告一段落了,具体的进阶使用我可能会在后续博文贴出,如Hubs通信模型解析,分组连接信息传输等,不过建议大家直接去阅读SignalR官方文档,查阅相关的Api就可以了,我相信普通技术的运用相对于理解还是要方便的。
这里额外推荐一篇SignalR的深入解读【打破砂系列】SignalR鬏方式剖析,这个博主也深入介绍了SignalR的自动选择和传输机制,也是一篇很棒的文章。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'SignalR + KnockoutJS + ASP.NET MVC4 实现井字游戏_CSS教程_
SignalR + KnockoutJS + ASP.NET MVC4 实现井字游戏
来源:人气:273
SignalR + KnockoutJS + .net MVC4 实现井字1.1.1 摘要
今天,我们将使用SignalR + KnockoutJS + ASP.NET MVC实现一个实时HTML5的井字棋游戏。
首先,网络游戏平台一定要让用户登陆进来,所以需要一个登陆模块,然后就是游戏设计并且在游戏过程中保持用户连接有效性,假设用户玩着玩着突然掉线这肯定会使用户很不爽;因此,保持客户端和服务端通讯的稳定性变得至关重要了,这里我们将使用SignalR和Html5保持通讯实时和稳定。
近一、两年來HTML5的发展是沸沸扬扬,在这其中你也许听过HTML5的规划给浏览器与服务器之间进行全双工通讯的WebSocket的通讯协定,并提供了的WebSocket API,这一套完整的API设计,在规格的部分,WebSocket的通讯协定已经于2011年被IETF(国际网路工程研究团队)定为标准的RFC 6455,而的WebSocket API则被W3C定为标准。目前各平台的浏览器的主流版本皆已经支援HTML5的WebSocket / WebSocket API。
WebSocket / WebSocket API企图解决开发者长久以来实现服务器推送技术几乎都依赖于轮询的方式所造成的明显缺点,使得服务器接受到太多请求,导致服务器资源过度占用以及带宽的浪费。
那么,我们使用WebSocket / WebSocket API就可以确保客户端和服务器通讯的稳定性,但我们要面对一个事实是不是每个用户的浏览器都支持HTML5,我们必须提高旧的浏览器支持方案。
SignalR的出现让ASP.NET的开发者得到了救赎,兼容的通讯协议设计将Comet ogramming概念和WebSocket技术都放在SignalR整个通讯架构中;SignalR会针对目前执行的浏览器进行判断,找到客户端(浏览器)与服务器最合适的建立链接方式。
SignalR会优先选用WebSocket技术与服务器沟通,开发人员就不需要针对浏览器而做出特殊的处理,所有的代码都通过ASP.NET SignalR高级的API进行信息传递。
图1 SignalR通讯的链接方式
ASP.NET MVC4 服务端
用户权限管理
游戏对象模型
SignalR的Hub模式
scrt客户端
SignalR代理方法
1.1.2 正文
首先,我们将使用ASP.NET MVC和SignalR实现服务端,客户端使用KnockoutJS和Html5获取和绑定数据到页面,具体设计如下图:
图2 井字棋游戏设计
我们使用SignalR提供一个简单的API用于创建服务器端到客户端的远程过程调用(RPC),以便从服务器端.NET代码中调用客户端浏览器(以及其他客户端平台)中的函数;客户端浏览器也可以通过SigalR来调用服务端.NET代码。
ASP.NET MVC4 服务端
接下来,我们要实现.NET服务器端,由于我们游戏平台是让用户登陆后进行游戏的,所以我们将实现用户帐户管理的模块。
首先,我们创建一个ASP.NET MVC4 Web 。
图3 ASP.NET MVC4 Web Application
这里我们选择Empty就可以了。
图4 ASP.NET MVC4 Web Application
然后,我们在项目中使用以下Nuget包:
install-package Microsoft.AspNet.SignalR
install-package jQuery
install-package KnockoutJS
用户权限管理
我们知道ASP.NET MVC自带的权限表的创建是在InitializeSimpleMembershipAttribute.cs中实现的,所以我们在程序中添加Filters文件夹,然后创建InitializeSimpleMembershipAttribute类,具体定义如下:
namespace OnlineTicTacTor.Filters{
/// &summary&
/// Simple Membership initializer.
/// &/summary&
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
private static SimpleMembershipInitializer _
private static object _initializerLock = new object();
private static bool _isI
public override void OnActionExecuting(ActionExecutingContext filterContext)
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
private class SimpleMembershipInitializer
public SimpleMembershipInitializer()
Database.SetInitializer&UsersContext&(null);
using (var context = new UsersContext())
if (!context.Database.Exists())
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
WebSecurity.InitializeDatabaseConnection(&DefaultConnection&, &UserProfile&, &UserId&, &UserName&, autoCreateTables: true);
catch (Exception ex)
throw new InvalidtionException(&The ASP.NET Simple Membership database could not be initialized.&, ex);
} }上面,我们定义了Web.ConfigInitializeSimpleMembershipAttribute类,接着我们在Web.config中的配置。
&connectionStrings&
&add name=&DefaultConnection& connectionString=&Data Source=(LocalDb)\v11.0;Initial Catalog=GamesDB;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\GamesDB.mdf& providerName=&System.Data.SqlClient& /&
&/connectionStrings&我们定义了数据库GamesDB,现在我们运行整个项目,看到localdb中生成了GamesDB数据库。  图5 GamesDB数据库由于,我们使用ASP.NET MVC自带的权限表来管理用户账号,这里会使用到表UserProfile和webpages_Membership,当然,如果有更复杂的权限管理,我们可以使用表webpages_Roles和webpages_UsersInRoles等。现在,我们已经创建了数据库GamesDB,接下来定义对应于数据表的DTO,首先,我们在Models文件夹中创建AccountModels.cs文件,然后定义类LoginModel具体定义如下:
/// &summary&
/// The DTO for user account.
/// &/summary&
public class LoginModel
[Required]
[Display(Name = &User name&)]
public string UserName { }
[Required]
[DataType(DataType.Pass)]
[Display(Name = &Password&)]
public string Password { }
[Display(Name = &Remember me?&)]
public bool RememberMe { }
} 上面,我们定义了数据传输类LoginModel,它包含了UserName、Password和RememberMe等信息。接下来,我们在Account文件中创建用户登陆页面Login.cshtml,由于时间的关系我们已经把页面设计好了,具体定下如下:@model OnlineTicTacTor.Models.LoginModel@{
ViewBag.Title = &Login&;}&section&
@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
@Html.AntiForgeryToken();
@Html.ValidationSummary();
&div class=&container&&
&div class=&content&&
&div class=&form-group&&
@Html.LabelFor(m =& m.UserName)
@Html.TextBoxFor(m =& m.UserName, new { @class = &form-control&, @placeholder = &UserName& })
@Html.ValidationMessageFor(m =& m.UserName)
&div class=&form-group&&
@Html.LabelFor(m =& m.Password)
@Html.PasswordFor(m =& m.Password, new { @class = &form-control&, @placeholder = &Password& })
@Html.ValidationMessageFor(m =& m.Password)
&div class=&checkbox&&
@Html.CheckBoxFor(m =& m.RememberMe)
@Html.LabelFor(m =&
优质网站模板

我要回帖

更多关于 signalr 教程 的文章

 

随机推荐