how to override SignalR methods in mvc 5 - model-view-controller

I am working on a asp.net mvc5 project and I want to implement chatroom with signalR So I got Microsoft.Aspnet.SignalR from nuget and I used a SignalR Hub class for hub and now i want to override OnDisconnected() method .but I get error
'ChatHub.OnDisconnected()': no suitable method found to override
I dont know how to solve this problem please help me
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace WebApplication3.Hubs
{
public class ChatHub : Hub
{
public void Hello()
{
Clients.All.hello();
}
static ConcurrentDictionary<string, string> dic = new ConcurrentDictionary<string, string>();
public void Send(string name, string message)
{
Clients.All.broadcastMessage(name, message);
}
public void SendToSpecific(string name, string message, string to)
{
// Call the broadcastMessage method to update clients.
Clients.Caller.broadcastMessage(name, message);
Clients.Client(dic[to]).broadcastMessage(name, message);
}
public void Notify(string name, string id)
{
if (dic.ContainsKey(name))
{
Clients.Caller.differentName();
}
else
{
dic.TryAdd(name, id);
foreach (KeyValuePair<String, String> entry in dic)
{
Clients.Caller.online(entry.Key);
}
Clients.Others.enters(name);
}
}
public override Task OnDisconnected()
{
var name = dic.FirstOrDefault(x => x.Value == Context.ConnectionId.ToString());
string s;
dic.TryRemove(name.Key, out s);
return Clients.All.disconnected(name.Key);
}
}
}

For SignalR 2.1.0+, you need to use OnDisconected(bool stopCalled).
// Microsoft.AspNet.SignalR.Hub
// Summary:
// Called when a connection disconnects from this hub gracefully or due to a timeout.
//
// Parameters:
// stopCalled:
// true, if stop was called on the client closing the connection gracefully; false,
// if the connection has been lost for longer than the Microsoft.AspNet.SignalR.Configuration.IConfigurationManager.DisconnectTimeout.
// Timeouts can be caused by clients reconnecting to another SignalR server in scaleout.
//
// Returns:
// A System.Threading.Tasks.Task
public virtual Task OnDisconnected(bool stopCalled);

Related

OData endpoint: Is it possible to edit document service

Dears,
I've designed a OData endpoint, following this https://learn.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint
I'm done with it but I have a constraint: for all API features, the header must contain an Authorization key. This is done everywhere BUT in the service document. The service document is what you got when looking at URL https://SITE/api/v1:
{"#odata.context":"http://SITE/api/v1/$metadata","value":[{"name":"things","kind":"EntitySet","url":"things"},{"name":"others","kind":"EntitySet","url":"others"}]}
Hence, do you know how is generated such document service? Is it possible to edit it? Or even, is there way to check header in such a document service?
Thanks in advance for your help,
Kind regards,
Solved by myself using following module:
using System;
using System.Linq;
using System.Web;
namespace Api.Modules
{
public class AuthorizationModule : IHttpModule
{
public void Dispose(){}
private void Context_Authorization(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
if (!IsAuthorized(application.Context))
{
application.Context.Response.Status = "403 Forbidden";
application.Context.Response.StatusCode = 403;
application.CompleteRequest();
}
}
public bool IsAuthorized(HttpContext context)
{
if (!HttpContext.Current.Request.Headers.AllKeys.Contains("Authorization"))
return false;
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
if (!authHeader.Equals(Properties.Resources.Authorization_Key))
{
return false;
}
return true;
}
public void Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(Context_Authorization);
}
}
}
If it helps...
Kind regards,

Entity Framework 6 "DbContext has been disposed" exception

Something very strange is happening in production, and it only happens in production. I have a Web API running and in one of the APIs, there is a repository created in the constructor and used in the functions. This is how the flow of a request works:
HTTP request comes in
MVC API controller decides which "worker" class to instantiate and creates it using Activator.CreateInstance
API controller calls worker.OnExecute inside of a Task.Run() and returns the http response
Worker calls _engine.Execute
Each worker instantiates another "engine" class that has all of the logic.
The engine in case constructs 3 repositories created using a UnitOfWork that is created per engine instance, like so:
public class MyWorker : Worker
{
private readonly MyEngine _engine;
public MyWorker()
{
_engine = new MyEngine();
}
protected override WorkerResult OnExecute(JObject data, CancellationToken cta)
{
return new WorkerResult(HttpStatusCode.OK, _engine.Execute(data));
}
}
public class MyEngine : EngineBase
{
private BaseRepository<Order> OrderRepo { get; set; }
private BaseRepository<OrderItem> OrderItemRepo { get; set; }
public MyEngine()
{
OrderRepo = new BaseRepository<Order>(MyUnitOfWork);
OrderItemRepo = new BaseRepository<OrderItem>(MyUnitOfWork);
}
public string Execute(JObject data)
{
return IsOrderValid(data).ToString();
}
public bool IsOrderValid(JObject data)
{
var orderId = data.Value<int>("OrderId");
// Without this line it crashes. With this line it crashes
//OrderRepo = new BaseRepository<Order>(InternationalWork);
// This is where it crashes
Order order = OrderRepo.First(x => x.OrderID == orderId);
// more code
}
}
public class EngineBase : UnitOfWorker, IDisposable
{
private UnitOfWork _myUnitOfWork;
public EngineBase() { }
public UnitOfWork MyUnitOfWork
{
get
{
return _myUnitOfWork ?? (_myUnitOfWork = new UnitOfWork(new DbContextAdapter(new MyDbContext())));
}
}
}
This is the actual stack trace:
The operation cannot be completed because the DbContext has been disposed.
StackTrace1
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.LazyInternalContext.get_ObjectContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.CreateObjectQuery(Boolean asNoTracking, Nullable`1 streaming, IDbExecutionStrategy executionStrategy)
at System.Data.Entity.Internal.Linq.InternalSet`1.InitializeUnderlyingTypes(EntitySetTypePair pair)
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
The stack trace shows "FirstOrDefault" because OrderRepo.First internally calls DbSet.FirstOrDefault, like so:
public virtual T First(Expression<Func<T, bool>> query)
{
return _dbSet.FirstOrDefault(query);
}
I'm stumped because each worker is created per http request. Each DBContext is created per engine instance so I don't know how it could be disposed when it was just created in the constructor. And this only happens on the production web server where I presume it's being called more. Any tips would be greatly appreciated.

Microsoft Dynamics CRM 2011

What is the difference between IOrganizationService and OrganizationServiceProxy in Dynamics CRM?
Is it related to accessing services in Crm context and outside Crm Context?
Simplest answer is IOrganizationService is an interface whereas OrganizationServiceProxy is a class which implements the IOrganizationService interface. This means any properties/methods on IOrganizationService are by default also available via OrganizationServiceProxy.
If running in the context of a plugin or custom workflow activity it will give you access to an IOrganizationService that you can use to interrogate CRM.
If you are writing something external, such as a windows service or standalone application, then you generally use the class OrganizationServiceProxy to set up a connection to the CRM web service. You can obviously assign this to an IOrganizationService later (e.g. dependency injection / for unit testing purposes). Or if you prefer there is no reason why you can continue to use the OrganizationServiceProxy.
The IOrganisationService is used within plugins and custom workflow activities and derived from the execution context.
While the OrganisationServiceProxy is mainly used for code running outside the Dynamics CRM application.
If you're using the sdk assemblies (specifically microsoft.xrm.sdk.dll), then you'll be using an implementation of IOrganizationService, and the call time will be identical. The main purpose of OrganizationServiceProxy is to provide options for establishing a connection to CRM in code that runs outside of CRM .The OrganizationServiceProxy class implements the IOrganizationService and provides an authenticated WCF channel to the organization service
OrganizationService is a higher level class that provides richer client side functionality and actually uses OrganizationServiceProxy inside it.
The Microsoft.Xrm.Client assembly that holds this higher level API cannot be used in Plugins etc but is intended for rich clients and ASP.NET.
It's worth noting that the Microsoft.Xrm.Client assembly has been removed from the CRM2016 SDK. For 2016 projects you might consider using the XRM Toolking assemblies.
See msdn.microsoft.com/.../dn689057.aspx
It has similar functionality that you mention around the connection manager -msdn.microsoft.com/.../mt608573.aspx
OrganizationServiceProxy is implementation of IOrganizationService. It is similar to case as List is implementation of interface IList. If to speak about why on Earth Microsoft provides both interface and implementation besides testing, I can propose one interesting case which happened in my life. I was in need of re-reading information from dynamics crm. In my case OrganizationServiceProxy got expired faster, then information was received from CRM. In order to fix it I've created following facade:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
namespace OrganizationService
{
public delegate IOrganizationService CreateOrganizationServiceFunc(string organizationServiceUrl, string userName, string password, TimeSpan? timeout = null, bool useSSL = false);
public class OrganizationServiceFacade : IOrganizationService
{
private IOrganizationService _serviceInternal { get; set; }
private CreateOrganizationServiceFunc _creator;
Func<IOrganizationService> _orgServiceFactory;
public OrganizationServiceFacade(Func<IOrganizationService> orgServiceFactory)
{
_orgServiceFactory = orgServiceFactory;
CreateService();
}
private void CreateService()
{
_serviceInternal = _orgServiceFactory();
}
public void Associate(string entityName, Guid entityId, Relationship relationship, EntityReferenceCollection relatedEntities)
{
try
{
_serviceInternal.Associate(entityName, entityId, relationship, relatedEntities);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
_serviceInternal.Associate(entityName, entityId, relationship, relatedEntities);
}
}
public Guid Create(Entity entity)
{
Guid result;
try
{
result = _serviceInternal.Create(entity);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
result = _serviceInternal.Create(entity);
}
return result;
}
public void Delete(string entityName, Guid id)
{
try
{
_serviceInternal.Delete(entityName, id);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
_serviceInternal.Delete(entityName, id);
}
}
public void Disassociate(string entityName, Guid entityId, Relationship relationship, EntityReferenceCollection relatedEntities)
{
try
{
_serviceInternal.Disassociate(entityName, entityId, relationship, relatedEntities);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
_serviceInternal.Disassociate(entityName, entityId, relationship, relatedEntities);
}
}
public OrganizationResponse Execute(OrganizationRequest request)
{
try
{
return _serviceInternal.Execute(request);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
return _serviceInternal.Execute(request);
}
}
public Entity Retrieve(string entityName, Guid id, ColumnSet columnSet)
{
try
{
return _serviceInternal.Retrieve(entityName, id, columnSet);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
return _serviceInternal.Retrieve(entityName, id, columnSet);
}
}
public EntityCollection RetrieveMultiple(QueryBase query)
{
try
{
return _serviceInternal.RetrieveMultiple(query);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
return _serviceInternal.RetrieveMultiple(query);
}
}
public void Update(Entity entity)
{
try
{
_serviceInternal.Update(entity);
}
catch (System.ServiceModel.Security.MessageSecurityException mex)
{
CreateService();
_serviceInternal.Update(entity);
}
}
}
}
and then I've got simple reconnect mechanism:
Trace.TraceInformation("Creation of CRM connection");
for (var maxTry = 0; maxTry < reconectionTries; maxTry++)
{
try
{
var service = new OrganizationServiceFacade(() =>
XrmServiceCreator.CreateOrganizationService("organizationServiceUrl",
"username",
"userpassword",
DefaultTimeout));
var response = (WhoAmIResponse) service.Execute(new WhoAmIRequest());
if (response.Results.Count == 0)
{
throw new InvalidDataException($"CRM returned no data in response. Number of retries is: {maxTry}, user name: {ConfigSettings.Default.RunAsUser}, Default timeout = {DefaultTimeout}");
}
return service;
}
catch (Exception e)
{
Trace.TraceError("Exception: {0}", e);
}
}
method XrmServiceCreator.CreateOrganizationService returns instance of IOrganizationService, and behind curtains it creates instance of OrganizationServiceProxy

How to invoke TraceListener.Write(object) through TraceSource

We have a custom TraceListener implementation which only logs when a specific object (LogMessage) is received. This all works well when using directly with the Trace.Write(object) method.
Due to Performance reason, I want to separate the Listener, so all non-relevant Trace messages are not passed to the listener. Therefore I created a specific TraceSource whith only this listener attached.
Now I struggle to pass my custom log object (LogMessage) to the listener using the TraceSource. The TraceSource.TraceData(TraceEventType, int, object) always invokes the TraceListener.Write(string) method, not the TraceListener.Write(object) method.
Is there any way I can pass the custom object to the Listener using the TraceSource?
Sample code:
using System.Diagnostics;
namespace Sample
{
public class LogMessage
{
public byte[] Data { get; set; }
//...
}
public class Sample
{
public void Foo()
{
var ts = new TraceSource("Test");
var lm = new LogMessage();
//lm.Data = ...;
//this works: calls the Write(object) method in listener
Trace.Write(lm);
//this doesn't work: calls the Write(string) method in listener
ts.TraceData(TraceEventType.Information, 0, lm);
}
}
public class MyListener : TraceListener
{
public override void Write(string message)
{
//not in use
}
public override void WriteLine(string message)
{
//not in use
}
public sealed override void Write(object o)
{
if (o is LogMessage)
{
//do someting with the LogMessage
}
}
}
}
Thanks
Thomas
maybe it's too late for an answer but anyway :
By using a tool like JustDecompile you can easily see that TraceSource.TraceData uses TraceListener.TraceData method which itself basically calls WriteLine with object.ToString() for message.
So you'll have to override the ToString method for your class LogMessage in order to do as you want.

SignalR in SharePoint

My project has a need for realtime user interaction and I think SignalR will solve my need. I'm technically on a SharePoint 2007 project, although I'm exclusively in application pages and thus barely use SharePoint at all. Regardless, I'm stuck in a 2.0 framework app pool in IIS.
My first approach was to try to create a 4.0 application as a sub-site. Unfortunately, that failed miserably. That approach works in a non-SharePoint world, but it appears that SharePoint has hijacked too much of the request pipeline for this approach to work for me.
So now I'm going down the path of creating a separate IIS Site that's 4.0 and using IIS rewrite rules to fake my app into thinking a particular subdirectory (/realtime/) is local and not a separate site so that I don't have to deal with cross domain request issues. The problem is I can't get IIS rewrite rules to rewrite to another http host (e.g. http://www.mySharepoint.com/_layouts/MySite/realtime/Hello.aspx to http://realtime.mySharePoint.com/Hello.aspx).
Any help with approach #1 or approach #2 or any alternative ideas would be greatly appreciated.
Here is what I did... Web App with signalR .net4.0, then your SharePoint Web App .net 2.
Add this to the global.asax in your Signalr project
RouteTable.Routes.MapHttpHandlerRoute("spproxy","spproxy/{*operation}", new SharePointRProxyHandler());
If you want to raise an event from SharePoint you can do a http POST to this new route URL for example
http://localhost:38262/spproxy
It will pass any posted data onto the httphandler below, that will then broadcast it to your clients.
Here is the code for MapHttpHandlerRoute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace System.Web.Routing
{
public class HttpHandlerRoute : IRouteHandler
{
private String _virtualPath = null;
private IHttpHandler _handler = null;
public HttpHandlerRoute(String virtualPath)
{
_virtualPath = virtualPath;
}
public HttpHandlerRoute(IHttpHandler handler)
{
_handler = handler;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
IHttpHandler result;
if (_handler == null)
{
result = (IHttpHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(IHttpHandler));
}
else
{
result = _handler;
}
return result;
}
}
public static class RoutingExtensions
{
public static void MapHttpHandlerRoute(this RouteCollection routes, string routeName, string routeUrl, string physicalFile, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null)
{
var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute(physicalFile));
RouteTable.Routes.Add(routeName, route);
}
public static void MapHttpHandlerRoute(this RouteCollection routes, string routeName, string routeUrl, IHttpHandler handler, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null)
{
var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute(handler));
RouteTable.Routes.Add(routeName, route);
}
}
}
Or you could just post directly to a httphandler and get the handler to do a connection.Broadcast
namespace SharePointRProxy
{
/// <summary>
/// Summary description for SharePointRProxyHandler
/// </summary>
public class SharePointRProxyHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
IConnectionManager connectonManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
IConnection connection = connectonManager.GetConnection<MyConnection>();
object payload = null; //Add payload here 'context.Request.Params["data"] ?'
JavaScriptSerializer jss = new JavaScriptSerializer();
var payloadJSON = jss.Serialize(payload);
connection.Broadcast(payloadJSON);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
You could also use either an event handler calling a .net 4.0 web service or an http handler to grab requests from SharePoint and pass them over to a .net 4.0 application running your signalr code.
You can see an example of using an http handler here: http://spmatt.wordpress.com/2012/04/12/harnessing-signalr-in-sharepoint/

Resources