2019年10月20日 By mikel 分类: 开发笔记, ASP.NET MVC

ASP.NET MVC 的SignalR发布IIS后项目提示跨域不能访问localhost的问题、

问题原因:SignalR需要访问localhost的signalr/Hubs的生成的js代码文件

解决版本:IIS站点绑定的是固定IP,而不是localhost导致了上述问题,直接改绑定未未分配就行了

Asp.NET MVC 的SignalR发布IIS后项目提示跨域不能访问localhost的问题已关闭评论
2019年10月17日 By mikel 分类: ASP.NET MVC

来源: asp.net-mvc – Chrome 27中SignalR和跨域请求的问题 – 脚本之家

编辑:这显然只是Chrome中的一个问题,它在FF和IE中运行良好Chrome版本:27.0.1453.116

我在localhost:13371上有一个简单的JS / HTML站点,我正在尝试访问localhost:13371上的SignalR中心.

无论何时发出请求,我都会收到以下错误:

XMLHttpRequest cannot load http://localhost:13370/signalr/hubs/negotiate?_=1372338722032. Origin http://localhost:13371 is not allowed by Access-Control-Allow-Origin.

我已经尝试过了:

>在Application_Start上启用SignalR上的跨域:

  1. RouteTable.Routes.MapHubs(new HubConfiguration { EnableCrossDomain = true });

>在SignalR服务器的Web.Config中启用跨域:

  1. <system.webServer>
  2. <httpProtocol>
  3. <customHeaders>
  4. <clear />
  5. <add name=“Access-Control-Allow-Origin” value=“*” />
  6. <add name=“Access-Control-Allow-Methods” value=“*” />
  7. <add name=“Access-Control-Allow-Headers” value=“*” />
  8. </customHeaders>
  9. </httpProtocol>
  10. </system.webServer>

>在JavaScript中设置信号器中心的连接URL:

  1. $.connection.hub.url = ‘http://localhost:13370/signalr/hubs’;

>在JQuery中启用CORS:

  1. $.support.cors = true;

>在Application_BeginRequest中手动设置响应头:

  1. protected void Application_BeginRequest(object sender,EventArgs e)
  2. {
  3. HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Origin”,“*”);
  4.  
  5. if (HttpContext.Current.Request.HttpMethod == “OPTIONS”)
  6. {
  7. //These headers are handling the “pre-flight” OPTIONS call sent by the browser
  8. HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Methods”,“GET,POST,PUT,DELETE”);
  9. HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Headers”,“*”);
  10. HttpContext.Current.Response.AddHeader(“Access-Control-Max-Age”,“1728000”);
  11. HttpContext.Current.Response.End();
  12. }
  13. }

以上都没有,也没有上述任何组合起作用.

附加信息:

>这两个站点都在Windows 7上的IIS中运行
> SignalR站点在端口13370上运行,作为.NET 4.0下MVC 4站点的一部分.
> JS / HTML站点是端口13371上的简单Web服务器,根本没有托管代码.
> SignalR站点肯定会响应浏览器对相关资源的直接请求.
> SignalR版本是1.1.2

解决方法

编辑:我现在找到了两个解决方案……方法1.摆脱你可能不需要的垃圾:

正如我在Stack Overflow question中发现的那样,基本上我在上面列出的“我尝试过的东西”中添加的几乎所有内容都是不必要的.修复步骤:

>删除我在上面尝试过的所有内容.这意味着在Web.Config或其他地方(如Global.asax)没有指定自定义标头,没有自定义JQuery设置等.
> ..除了RouteTable.Routes.MapHubs(new HubConfiguration {EnableCrossDomain = true});在Application_Start中.
>你还需要设置$.connection.hub.url =’http:// localhost:13370 / signalsr / hubs’;

… 而已.这可能是最好的解决方案,也是我最终使用的解决方案.

方法2.如果您在Chrome中仍然遇到问题,请使用jsonp:

如果你在Chrome中仍然遇到这样的问题,可以使用jsonp让协商脚本正确下载…将以下内容添加到我的JavaScript中心开始解决问题:

  1. //detect chrome
  2. var isChrome = navigator.userAgent.toLowerCase().indexOf(‘chrome’) > 1;
  3.  
  4. //set the connection url.
  5. $.connection.hub.url = ‘http://localhost:13370/signalr/hubs’;
  6.  
  7. //use jsonp if chrome
  8. $.connection.hub.start({
  9. jsonp: isChrome
  10. });

可能有一种更好的方法来测试浏览器功能并相应地设置jsonp ……看着用户代理感觉很脏……但是这解决了我在过渡时期的问题.我希望这有助于其他人.

总结

以上是脚本之家为你收集整理的asp.net-mvc – Chrome 27中SignalR和跨域请求的问题全部内容,希望文章能够帮你解决asp.net-mvc – Chrome 27中SignalR和跨域请求的问题所遇到的程序开发问题。

asp.net-mvc – Chrome 27中SignalR和跨域请求的问题 – 脚本之家已关闭评论
2019年10月17日 By mikel 分类: ASP.NET MVC, C#

来源: SignalR 和跨域问题 (ASP.NET MVC) – chen.s – 博客园

SignalR 有三块,

Server:
Hub Server
Custom Message Sender Service (Sender Proxy)

Client:
Message Sender
Message Receiver

1. Hub Server & Sender Proxy Service
Hub Server 和 Custom Message Sender Service 在一个app中,“Custom Message Sender Service” 通过api直接控制Hub Server行为。(connection filtering, status, deliver message, etc )

2. 跨域
Sender, Receiver 和 Hub Server 可能都不在同一个域里。 会有跨域访问的问题。

3. 发消息的客户端
可以有两种方式发消息给Hub Server
3.1 通过hubproxy.server.func(), 走的是signalR的persistent connection. (这种情形下一般只发一次消息,persistent connection占用了资源,浪费。 当然也可以建立完释放,persistent connection -> send message -> close persistent connection)。 这种模式下,跨域由SignalR Hub框架控制。
3.2 通过ajax调用 “Custom Message Sender Service (Proxy)”, 由Proxy调用Hub的服务。 这种结构更干净,发送者和SignalR connection没有关系, 走单独Http请求。 跨域由 “Custom Message Sender Service (Proxy)”, 一般由服务端暴露服务(MVC/WebAPI). 但是MVC和WebApi的跨域管理不太一样。(见“MVC和WebApi的跨域管理”)
3.3 有一种情况可以考虑用signalR的persistent connection发消息。 就是发消息的人,同时又是收消息的人。 那么一个persistent connection可以同时用来收发消息。

4. 收消息的客户端
这个只有一种,“持久连接,保持监听”。
4.1 SignalR保持连接的方式由协议本身定义,由服务器和浏览器支持。 WebSocket / iFrame / longPooling。 具体可google
4.2 WebSocket的效率要比其他高很多,比较reliable,比如disconnect, 其他方式可能不能直接反应客户端关闭的动作,需要等待超时发生触发disconnect. 代码和排错上有时比较费解。
4.3 【Hub Server服务端】微软的WebApp PaaS上, by default, “WebSocket”不enable。要去管理界面把它打开。

5. Hub Server
5.1 Owin中map /signalr 作为SignalR routing的开始
(https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#tracing If you are adding SignalR functionality to an ASP.NET MVC application, make sure that the SignalR route is added before the other routes. For more information, see Tutorial: Getting Started with SignalR 2 and MVC 5.)
5.2 跨域访问由Owin框架自己处理, 如果再由IIS web.config来控制CORS, 会产生冲突。
5.3 Hub Server中的方法,只是个签名,具体实现不重要(无需写实现,除非客户端用hub.server.func()发消息)。 主要作用
5.3.1 生成客户端代理类。
5.3.2 让代理类绑定本地方法,以被服务端调用

 6. Sender Message Proxy
6.1 如果用MVC做,有个很大的问题就是,跨域。
6.1.1 如果浏览器是IE, 问题不是很大。 貌似preflight request 被省略了。 request 被直接提交到MVC层, 可以自定义Action属性, 加入”Access-Control-Allow-Origin“。
6.1.2 如果浏览器是Chrome, “preflight request”不会被忽略. http option verb会发过来。 这个时候MVC就有问题了, 无论从owin还是application_beginRequest,都无法获得这个request,无法修改http头,使得CORS通过。 (MVC 不能intercept http option request,而webapi能,webapi 是不是因为引用了system.web.http.webhost 才能intercept?)
6.1.3 对于simple CORS, IE 和 Chrome (Chrome 无须preflight), 如果用Get/Post传数据,由于不走preflight, 自定义Action属性修改http header是可行的。 但是如果用ajax, 有content type header的话, 那就必须要走preflight.

7. IIS setting, web.config
实际使用当中,如果使用MVC 和 SignalR, 客户端用ajax post json (content type = application / json), 那么需要考虑直接使用直接从服务器设置应用CORS。 这个时候SignalR的CORS需要被取消(//map.UseCors(CorsOptions.AllowAll) )

<add name=”Access-Control-Allow-Origin” value=”https://localhost:44300″ />
<add name=”Access-Control-Allow-Headers” value=”Content-Type” />
<add name=”Access-Control-Allow-Credentials” value=”true” />

 

CORS 介绍

一篇很好的文章介绍CORS:https://staticapps.org/articles/cross-domain-requests-with-cors/

注意Simple CORS / Complex CORS 的区别

备注
尽量少用IE来做测试,用Chrome或firefox比较标准,会得到和预期一致的结果。 IE的结果经常莫名其妙,比如SignalR不enable CORS (map.UseCors(CorsOptions.AllowAll);)在localhost下,跨域的连接居然也能成功。

 

常用代码

var heartBeat GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>();
var connectionAlive = heartBeat.GetConnections().FirstOrDefault(c=>c.ConnectionId == connection.ConnectionId);
if (connectionAlive.IsAlive)
{//Do whatever...}

======================================================

IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
IHubContext context = GlobalHost.ConnectionManager.GetHubContext(“MyHub”);

======================================================

public class EnableCorsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader(“Access-Control-Allow-Origin”, “*”);
base.OnActionExecuting(filterContext);
}
}

SignalR 和跨域问题 (ASP.NET MVC) – chen.s – 博客园已关闭评论
2019年10月17日 By mikel 分类: ASP.NET MVC, C#

来源: asp.net core 使用SignalR跨域请求出现的坑 – a914541185的博客 – CSDN博客

前段时间因为工作需要,认识到了SignalR,这个东西本身挺好用,但是在处理跨域问题上是遭遇了很大的坑。

我在本地通过localhost连接的时候毫无问题,但是当我在前端使用IP来连接我的后台,则会出现连接失败的问题。查阅了很多,询问公司内的大牛之后,找到一个正确解决方案,特记录如下:

首先,在Strartup.cs文件下处理跨域问题

public const string CorsName = “SignalRCors”;

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddSignalR();
services.AddCors(options =>
{
options.AddPolicy(CorsName,
policy => policy.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
});
services.AddMvc((opt) =>
{
opt.Filters.Add(new CorsAuthorizationFilterFactory(CorsName));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(“/Error”);
app.UseHsts();
}
app.UseCors(CorsName);
之后右键你的项目进入属性-调试,记下你的http端口号以及htts的端口号

然后找到applicationhost.config文件,一般路径是项目文件夹\.vs\config\applicationhost.config。找到如下代码

<sites>
<site name=”WebSite1″ id=”1″ serverAutoStart=”true”>
<application path=”/”>
<virtualDirectory path=”/” physicalPath=”%IIS_SITES_HOME%\WebSite1″ />
</application>
<bindings>
<binding protocol=”http” bindingInformation=”:8080:localhost” />
</bindings>
</site>
<site name=”signalrTotest” id=”2″>
<application path=”/” applicationPool=”Clr4IntegratedAppPool”>
<virtualDirectory path=”/” physicalPath=”C:\Users\JC.YX\Desktop\signalrTotest\signalrTotest” />
</application>
<bindings>
<binding protocol=”https” bindingInformation=”:44331:localhost” />
<binding protocol=”http” bindingInformation=”:35000:localhost” />
</bindings>
</site>
可以看到有https和http的端口设置,以及允许localhost连接。这时我们只需要在它们下面添加自己的IP地址就可以了。添加之后的代码如下

<sites>
<site name=”WebSite1″ id=”1″ serverAutoStart=”true”>
<application path=”/”>
<virtualDirectory path=”/” physicalPath=”%IIS_SITES_HOME%\WebSite1″ />
</application>
<bindings>
<binding protocol=”http” bindingInformation=”:8080:localhost” />
</bindings>
</site>
<site name=”signalrTotest” id=”2″>
<application path=”/” applicationPool=”Clr4IntegratedAppPool”>
<virtualDirectory path=”/” physicalPath=”C:\Users\JC.YX\Desktop\signalrTotest\signalrTotest” />
</application>
<bindings>
<binding protocol=”https” bindingInformation=”:44331:localhost” />
<binding protocol=”https” bindingInformation=”:44331:192.168.0.104″ />
<binding protocol=”http” bindingInformation=”:35000:localhost” />
<binding protocol=”http” bindingInformation=”:35000:192.168.0.104″ />
</bindings>
</site>
这时,将你的前端代码修改为对应IP地址加端口号,启动IIS服务,你可以尽情的和朋友在聊天室里聊天了

var connection = new signalR.HubConnectionBuilder().withUrl(“http://yourIP:35000/chatHub”).build();
注意:如果你前端写的是http协议,请在启动IIS服务之后,将默认打开的网址修改为http协议加对应的端口号。
————————————————
版权声明:本文为CSDN博主「是豆腐啊」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a914541185/article/details/83181919

asp.net core 使用SignalR跨域请求出现的坑 – a914541185的博客 – CSDN博客已关闭评论
2019年10月14日 By mikel 分类: C#

来源: CefSharp High DPI问题的解决

使用CefSharp控件,在部分高分辨率的电脑中(显示缩放比例非100%,而是120%或者125%等)会出现以下一些情况:

技术分享图片

技术分享图片

显示的页面中出现了黑边,且按钮定位也偏了,比如点击【图层】按钮,需要点击上面黑色边框中的相对位置。

 

解决方案:

1、在当前电脑的桌面,右键-显示设置,把显示比例调整为100%(需要重启电脑生效),这时再看,显示就正常了;

2、在当前项目中,添加一个【应用程序清单文件】(app.manifest),在根节点(assembly)下,添加以下代码,重新运行程序,则和方法1的效果就一样了:

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>

3、使用CefSharp自带的方法:

找到Cef.Initialize(setting);语句,在其下添加Cef.EnableHighDPISupport();

当程序加载了ChromiumWebBrowser控件后,就会把当前的显示比例调整为100%了

            Cef.Initialize(setting);
            Cef.EnableHighDPISupport();

 

优先选择 【方法3】

CefSharp High DPI问题的解决已关闭评论
2019年10月14日 By mikel 分类: C#, Debug

来源: 使用cefsharp 浏览器放大-布布扣-bubuko.com

(1)如果浏览器位置有问题,需要设置 Cef.EnableHighDPISupport();

(2)如果要放大浏览器,需要设置  browser.SetZoomLevel(1.25);

        ChromiumWebBrowser webbrowser = new ChromiumWebBrowser(""); 
        private void Form1_Load(object sender, EventArgs e)
        {


            Cef.EnableHighDPISupport();

            this.FormBorderStyle = FormBorderStyle.None;
            this.WindowState = FormWindowState.Maximized;



            string url = System.Configuration.ConfigurationManager.AppSettings["url"];
            webbrowser = new ChromiumWebBrowser(url);

            // Add it to the form and fill it to the form window.
           
            
            webbrowser.Dock = DockStyle.Fill;
            webbrowser.FrameLoadEnd += webbrowser_FrameLoadEnd;
            this.Controls.Add(webbrowser);

void webbrowser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)         {

ChromiumWebBrowser browser = (ChromiumWebBrowser)sender;

browser.SetZoomLevel(1.25);

}

使用cefsharp 浏览器放大-布布扣-bubuko.com已关闭评论
2019年10月14日 By mikel 分类: C#

来源: cef网页缩放策略 – mmthr的博客 – CSDN博客

最近遇到一些2K屏在高DPI下由于设置cef禁止缩放导致页面文件很小,看不清导致用户体验很差的问题。

为了解决这个问题,采用了控制cef缩放比例的方式来解决。

在OnBeforeCommandLineProcessing 中通过设置

double scale = GetAutoScale();

GetAutoScale()的想法是获取当前的DPI,计算一个合适的缩放比率,来保证页面显示正常。
command_line->AppendSwitchWithValue(“–device-scale-factor”, to_string(scale)); 来获取适应的DPI。

针对某些非2K屏,可以使用command_line->AppendSwitchWithValue(“–force-device-scale-factor”, “1”); 来禁止缩放。
————————————————
版权声明:本文为CSDN博主「mmthr」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mmthr/article/details/87697172

cef网页缩放策略 – mmthr的博客 – CSDN博客已关闭评论
2019年10月14日 By mikel 分类: Debug

来源: 移动硬盘无法读取分区表修复RAW格式修复 – 学而思(xiejava的blog) – CSDN博客

突然发现连在玩客云上的320G西数的移动硬盘读不出了,拔出来后连在台式机笔记本上都是无法识别。摸了一下硬盘还在转,想了好多办法都修复不了,上网查了一下应该是分区表被损坏了。
后来用台式机通过老毛桃的winpe系统,用里面的磁盘修复工具一个一个的试。首先是HDTunePro对磁盘进行健康扫描发现没有啥问题,就是读不出。说明硬盘还没有物理损坏,接着用DiskGenius修复分区表
具体是在识别到了硬盘的情况下,选中硬盘的盘符后选择“搜索已丢失分区(重建分区表)”

然后对硬盘的健康情况进行检测。 右键硬盘盘符,选择“坏道检测与修复”

检测完后发现也没有什么坏道。

重建分区表后,发现可以找到盘符了,但是有个最大的盘200G的还是没有办法打开,仔细一看文件系统是RAW,不是原来的NTFS了。看来是文件系统损坏了,又是一顿狂找资料看如何才能将RAW的文件系统还原成NTFS。后来找到一个非常有效的办法。就是用chkdsk。
在win10下用超级管理员的方式打开命令行,输入chkdsk I: /f

运行了很久以后检查完成后终于将RAW转换成了NTFS,硬盘可以正常访问,数据也没有丢失。

为什么会出现RAW呢,网上是说经常不正常插拔断电都会顺坏分区表和文件系统。移动硬盘还是很脆弱的。以后要多加小心。
————————————————
版权声明:本文为CSDN博主「xiejava1018」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fullbug/article/details/79591684

移动硬盘无法读取分区表修复RAW格式修复 – 学而思(xiejava的blog) – CSDN博客已关闭评论
2019年10月14日 By mikel 分类: C#, Debug

来源: [VS2017][C#]打包发布安装版程序(修改默认安装地址/卸载等) – 身披白袍’s博客 – CSDN博客

Step1:安装插件
点击工具-扩展和更新-搜索Microsoft Visual Studio 2017 Installer Projects-安装该插件,然后重启Visual Studio直至将该插件安装完毕。

Step2:打包可执行程序及依赖库
接下来要打包可执行程序和依赖库(dll ini等文件):
打开现有项目,右键新建项目:

三个文件夹,分别指向要发送到[文件安装目录下/桌面/开始菜单]中的文件。
首先,要把项目生成的exe等文件送进去,可以选择文件…添加,或是直接通过项目输出添加。

如果选择后者,注意发布的版本和位数:

然后,为输出文件添加快捷方式。右键,相关项目,选择shortcut。

快捷方式可以拖动到[桌面]或是[菜单],如果要拖动到菜单,建议先建立一个文件夹Add Folder…,然后把该快捷方式添加进去(后期可能还要添加卸载文件的快捷方式到这个文件夹中)。

最后,别忘了把依赖和所需要的一些其他文件(配置文件等),添加到Application Folder中,不然你的程序可是没法执行的。
先生成一下项目,去生成一个安装包工程的配置文件,有一定情况会生成失败,下面再继续完善这个安装包。

Step3:制作卸载程序
新建一个项目,键入以下代码,其中中间的C2B7E983-AA2A…-820B是安装包的产品号,可以在上面刚刚生成的安装包工程的配置文件中,利用Ctrl+F搜索ProductCode获得。

产品号:

修改产品号后,生成Uninstall.exe,作为一个依赖文件添加到Application Folder中(当然,你也可以给它添加快捷方式及快捷方式图标)。

其他
修改Default Company Name,还是打开刚刚生成的配置文件InstallerMakerXXXXX.vdproj,Ctrl+F搜索相关值,把其改为相应

错误
is not compatible with the project’s target platform ‘x86’
首先要确认你的项目的目标平台是否选择正确(项目属性-生成/配置-TargetPlatForm/目标平台),如果依旧报错,打开InstallerMakerXXXXX.vdproj,搜索键值TargetPlatform:

“TargetPlatform” = “3:0”
1
3:0改为3:1是x64,3:2是X86。
————————————————
版权声明:本文为CSDN博主「身披白袍」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Shenpibaipao/article/details/83152955

[VS2017][C#]打包发布安装版程序(修改默认安装地址/卸载等) – 身披白袍’s博客 – CSDN博客已关闭评论
2019年10月14日 By mikel 分类: ASP.NET MVC, ASP.NET

来源: Asp.net SignalR 实现服务端消息推送到Web端 – PetterLiu – 博客园

之前的文章介绍过Asp.net SignalR,  ASP .NET SignalR是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.  今天我们来实现服务端消息推送到Web端,   首先回顾一下它抽象层次图是这样的:

image

实际上 ASP.NET SignalR 2 实现 服务端消息推送到Web端, 更加简单. 为了获取更好的可伸缩性, 我们引入消息队列, 看如下基本流程图:

image

消息队列MQ监听, 在Web site 服务端一收到消息,马上通过Signalr 推送广播到客户端.  创建ASP.NET MVC WEB APP,  从NuGet 安装SignalR 2.12

Install-Package Microsoft.AspNet.SignalR

具体实现代码,是这样的,我们增加一个空的Hub:

    public class FeedHub : Hub
    {
        public void Init()
        {
        }
    }

是简单的消息模型, 标题与正文属性:

    [Serializable]
    public class PushMessageModel
    {
        public int Id { get; set; }
        public string MSG_TITLE { get; set; }
        public string MSG_CONTENT { get; set; }
    }

服务端推送具体类,记录日志, 创建消息队列实例,监听, 等待收取消息. 这里我们使用的是AcitveMQ的.net客户端. ActiveMQListenAdapter是一个封装过的对象.

    public class MQHubsConfig
    {
        private static ILogger log = new Logger("MQHubsConfig");

        /// <summary>
        /// Registers the mq listen and hubs.
        /// </summary>
        public static void RegisterMQListenAndHubs()
        {
            var activemq = Megadotnet.MessageMQ.Adapter.ActiveMQListenAdapter<PushMessageModel>.Instance(MQConfig.MQIpAddress, MQConfig.QueueDestination);
            activemq.MQListener += m =>
            {
                log.InfoFormat("从MQ收到消息{0}", m.MSG_CONTENT);
                GlobalHost.ConnectionManager.GetHubContext<FeedHub>().Clients.All.receive(m);
            };

            activemq.ReceviceListener<PushMessageModel>();
        }
    }

上面有一句关键代码GlobalHost.ConnectionManager.GetHubContext<FeedHub>().Clients.All.receive(m);  这里使用了GetHubContext方法后,直接来广播消息.

需要在MVCApplication下加载:

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            MQHubsConfig.RegisterMQListenAndHubs();
        }
    }

同时需要增加一个Starup.cs, 用于Owin

[assembly: OwinStartup(typeof(RealTimeApp.Startup))]
namespace RealTimeApp
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

接下来是客户端App.js:

function App() {
    var init = function () {
        Feed();
        $.connection.hub.logging = true;
        $.connection.hub.start()
            .done(function() {
                console.log("Connected!");
                $(document).trigger("Connected");
            })
            .fail(function() { console.log("Could not Connect!"); });
    };

    init();
};

Feed.js 具体与SignalR.js通信, 创建名为receive的function, 与服务端对应

function Feed() {
    var chat = undefined;

    var init = function () {

        // Reference the auto-generated proxy for the hub.
        chat = $.connection.feedHub;
        // Create a function that the hub can call back to display messages.
        chat.client.receive = function (item) {
            var selector = "ul.feed-list li[data-id=" + item.Id + "]";
            if (!($(selector).length > 0)) {
                $("ul.feed-list").prepend($(".feed-template").render(item));
                $("ul.feed-list li:gt(3)").remove();
            }

            $.messager.show({
                title: 'Tips',
                msg: item.MSG_CONTENT,
                showType: 'show'
            });


        };

        // Start the connection.
        $.connection.hub.start().done(function () {
            chat.server.init();
        });

    };

    init();
};

上面的JavaScript代码与服务端有通信, 具体看如下图:

image

在Index.cshtml,  我们需要引用SignalR客户端JS, 放置hubs, 这里我们使用了jsrender,  easyui.js 来呈现推送的消息.

@model dynamic

@section Scripts {
<link href="/Content/themes/default/window.css" rel="stylesheet" />
<link href="~/Content/themes/default/progressbar.css" rel="stylesheet" />
<link href="~/Content/themes/default/linkbutton.css" rel="stylesheet" />
<script src="~/Scripts/jquery.signalR-2.1.2.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>

<script src="~/Scripts/jsrender.js"></script>
<script src="~/Scripts/jquery.easyui.min-1.4.1.js"></script>

@Scripts.Render("~/Scripts/project.js")

    <script type="text/javascript">
        $(document).ready(function () {
            var app = new App();
        });

    </script>
}


<div class="row-fluid">

    <div class="span8">
        <div class="widget">
            <div class="widget-header">
                <h2>Feed</h2>
            </div>
            <div class="widget-content">
                <ul class="span12 feed-list"></ul>
            </div>
        </div>
    </div>
</div>

<script class="chat-template" type="text/x-jquery-tmpl">
    <li>
        <p>{{>Message}}</p>
    </li>
</script>

<script class="feed-template" type="text/x-jquery-tmpl">
    <li data-id="{{>Id}}">
        <div class="row-fluid">

            <div class="span8">
                <h3>{{>MSG_CONTENT}}</h3>
            </div>
        </div>
    </li>
</script>

上代码服务端引用js的Script.Render, 需要在BundleConfig.cs中加入以下代码:

          bundles.Add(new ScriptBundle("~/Scripts/project.js")
              .IncludeDirectory("~/Scripts/Project", "*.js", false));

同时我们构建一个WebAPI来发送需要推送的消息, 片断代码:

        /// <summary>
        /// SendMessage
        /// </summary>
        /// <param name="messagemodel">The messagemodel.</param>
        /// <returns></returns>
        [HttpPost]
        public IHttpActionResult SendMessage(PushMessageModel messagemodel)
        {
            return SendToServer(messagemodel);

        }

        /// <summary>
        /// Sends to server.
        /// </summary>
        /// <param name="messagemodel">The messagemodel.</param>
        /// <returns></returns>
        private IHttpActionResult SendToServer(PushMessageModel messagemodel)
        {

            if (ModelState.IsValid)
            {
                if (messageRepository.SendMessage(messagemodel))
                {
                    log.Debug("发送成功!");
                    return Ok();
                }
                else
                {
                    log.ErrorFormat("发送失败!{0}", messagemodel);
                    return Content(HttpStatusCode.ExpectationFailed, new Exception("send message error"));
                }
            }
            else
            {
                log.ErrorFormat("参数验证失败!{0}", messagemodel);
                return Content(HttpStatusCode.BadRequest, ModelState);
            }

        }

发送消息到ActiveMQ的关键代码:

    public class MessageRepository:IMessageRepository
    {
        private static ILogger log = new Logger("MessageRepository");

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="messagemodel"></param>
        /// <returns></returns>
        public bool SendMessage(PushMessageModel messagemodel)
        {
          var activemq = new ActiveMQAdapter<PushMessageModel>(MQConfig.MQIpAddress, MQConfig.QueueDestination);
          return activemq.SendMessage<PushMessageModel>(messagemodel)>0;
        }
    }

 

如果您需要运行DEMO程序,需要构建基于ActiveMQ的消息队列,   运行效果是这样的, 我们在一个静态html中, 发送一个ajax到webapi服务端,  发送后

image

另一个website网站收到后, 列表更新, 并在右下角弹出框

image

IE的控制台输出:

HTML1300: Navigation occurred.
File: Index
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Client subscribed to hub ‘feedhub’.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Negotiating with ‘/signalr/negotiate?clientProtocol=1.4&connectionData=%5B%7B%22name%22%3A%22feedhub%22%7D%5D’.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: This browser doesn’t support SSE.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Binding to iframe’s load event.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Iframe transport started.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: foreverFrame transport selected. Initiating start request.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: The start request succeeded. Transitioning to the connected state.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332 and a connection lost timeout of 20000.
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Invoking feedhub.Init
Connected!
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Invoked feedhub.Init
[11:07:12 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event ‘receive’ on hub ‘FeedHub’.
[11:07:18 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event ‘receive’ on hub ‘FeedHub’.
[11:07:32 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event ‘receive’ on hub ‘FeedHub’.
[11:07:51 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event ‘receive’ on hub ‘FeedHub’.
[11:09:25 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event ‘receive’ on hub ‘FeedHub’.

上面粗体是 最后我们发的第5条信息控制台的输出.

 

好了,到这儿, 由于篇幅有限, 示例代码没有全部展示, 可以在这儿下载,  需要安装ActiveMQ

 

希望对您开发实时Web App有帮助.

你可能感兴趣的文章:

SignalR介绍与Asp.net

如有想了解更多软件,系统 IT,企业信息化 资讯,请关注我的微信订阅号:

MegadotnetMicroMsg_thumb1_thumb1_thu[1]

Asp.net SignalR 实现服务端消息推送到Web端 – PetterLiu – 博客园已关闭评论
备案信息冀ICP 0007948