SignalR structuremap dependency resolver ( specified for Microsoft.AspNet.SignalR.Messaging.IMessageBus ) - signalr

how can i resolve this error ?
versions
Microsoft.AspNet.SignalR.Core 2.2.0, structuremap 3.1.4.143
global.asax signalR dependency resolve
// SIGNALR DEPENDENCY RESOLVER
GlobalHost.DependencyResolver = new StructureMapSignalRDependencyResolver(Container ?? ObjectFactory.Container);
StructureMapSignalRDependencyResolver
public class StructureMapSignalRDependencyResolver : DefaultDependencyResolver
{
private readonly IContainer _container;
public StructureMapSignalRDependencyResolver(IContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
object service = null;
//Below is a key difference between this StructureMap example, GetInstance is used for concrete classes.
if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
{
//If the type is a concrete type we get here...
service = _container.GetInstance(serviceType);
}
else
{
// Non concrete resolution which uses the base dependency resolver if needed.
service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
}
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var objects = _container.GetAllInstances(serviceType).Cast<object>();
return objects.Concat(base.GetServices(serviceType));
}
}
erorr
No default Instance is registered and cannot be automatically determined for type 'Microsoft.AspNet.SignalR.Messaging.IMessageBus'
There is no configuration specified for Microsoft.AspNet.SignalR.Messaging.IMessageBus
1.) new AckSubscriber(Default of IMessageBus, Default of IAckHandler)
2.) Microsoft.AspNet.SignalR.Infrastructure.AckSubscriber
3.) Instance of Microsoft.AspNet.SignalR.Infrastructure.AckSubscriber
4.) Container.GetInstance(Microsoft.AspNet.SignalR.Infrastructure.AckSubscriber)

Try to resolve from the base class first.
public override object GetService(Type serviceType)
{
if (serviceType == null)
return null;
var service = base.GetService(serviceType);
if (service != null) return service;
return (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
? container.GetInstance(serviceType)
: container.TryGetInstance(serviceType);
}

#ajm answer above bypassed the error for me, however I found that none of my client-side methods were being invoked.
It turned out that SignalR.Infrastructure.PrincipalUserIdProvider was being resolved instead of my custom IUserIdProvider so I had to modify his answer slightly by adding a container check first.
public override object GetService(Type serviceType)
{
if (serviceType == null)
return null;
var service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
if (service != null) return service;
return (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
? _container.GetInstance(serviceType)
: _container.TryGetInstance(serviceType);
}
The secondary container checks are still necessary if you are not using StructureMap 3 as TryGetInstance() returns null for concrete types.

I found temporary, but error continues..
how can i registry this {Name = "AckSubscriber" FullName = "Microsoft.AspNet.SignalR.Infrastructure.AckSubscriber"}
temporary solution is try catch, in catch return null
public override object GetService(Type serviceType)
{
try
{
object service = null;
//Below is a key difference between this StructureMap example, GetInstance is used for concrete classes.
if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
{
//If the type is a concrete type we get here...
service = _container.GetInstance(serviceType);
}
else
{
// Non concrete resolution which uses the base dependency resolver if needed.
service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
}
return service;
}
catch (Exception exc)
{
return null;
}
}

I just had a similar problem using a Ninject based resolver. The solution in that case was to ensure that Ninject had a binding for IDependencyResolver, similar to this.
var resolver = new NinjectResolver(kernel);
kernel.Bind<IDependencyResolver>().ToConstant(resolver);
GlobalHost.DependencyResolver = resolver;
AckSubscriber has 2 constructors.
public AckSubscriber(IDependencyResolver resolver)
public AckSubscriber(IMessageBus messageBus, IAckHandler ackHandler)
It would appear that for some reason, rather than trying to create this class via a dependency resolver, it is trying to create this class via the underlying IOC container. Because the bindings for all of this classes are in the DefaultDependencyResolver, the container has no idea what they are and so errors. By specifying a binding for IDependencyResolver it is able to use the first constructor and work as intended.

Related

Missing owin context

I'm trying to use the ResourceAuthorize attribute from Thinktecture.IdentityModel, but everything stops because there is no owin context.
I have a owin startup class which setups the authorization manager
[assembly: OwinStartup(typeof(My.WebApi.Startup))]
namespace My.WebApi
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
AuthConfig.Configure(app);
}
}
}
public class AuthConfig
{
public static void Configure(IAppBuilder app)
{
app.UseResourceAuthorization(new ResourceAuthorizationMiddlewareOptions
{
Manager = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IResourceAuthorizationManager)) as IResourceAuthorizationManager
});
}
}
and I know that it is detected and invoked. But later on, when hitting the following code from IdentityModel, I get a null pointer exception:
public static Task<bool> CheckAccessAsync(this HttpRequestMessage request, IEnumerable<Claim> actions, IEnumerable<Claim> resources)
{
var authorizationContext = new ResourceAuthorizationContext(
request.GetOwinContext().Authentication.User ?? Principal.Anonymous,
actions,
resources);
return request.CheckAccessAsync(authorizationContext);
}
I have stepped through and sees that it's caused by the GetOwinContext() returning null, since there is no MS_OwinContext or MS_OwinEnvironment property on the request.
What am I missing?
UPDATE:
I have found that i have an owin.environment property available, but it's part of the `HttpContextWrapper, not the request.
By searching around, I found some code inside of System.Web.Http.WebHost.HttpControllerHandler that looks like it should have converted the owin.environment to an MS_OwinEnvironment, but apparently, that code is never called in my case...
internal static readonly string OwinEnvironmentHttpContextKey = "owin.Environment";
internal static readonly string OwinEnvironmentKey = "MS_OwinEnvironment";
internal static HttpRequestMessage ConvertRequest(HttpContextBase httpContextBase, IHostBufferPolicySelector policySelector)
{
HttpRequestBase requestBase = httpContextBase.Request;
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethodHelper.GetHttpMethod(requestBase.HttpMethod), requestBase.Url);
bool bufferInput = policySelector == null || policySelector.UseBufferedInputStream((object) httpContextBase);
httpRequestMessage.Content = HttpControllerHandler.GetStreamContent(requestBase, bufferInput);
foreach (string str in (NameObjectCollectionBase) requestBase.Headers)
{
string[] values = requestBase.Headers.GetValues(str);
HttpControllerHandler.AddHeaderToHttpRequestMessage(httpRequestMessage, str, values);
}
HttpRequestMessageExtensions.SetHttpContext(httpRequestMessage, httpContextBase);
HttpRequestContext httpRequestContext = (HttpRequestContext) new WebHostHttpRequestContext(httpContextBase, requestBase, httpRequestMessage);
System.Net.Http.HttpRequestMessageExtensions.SetRequestContext(httpRequestMessage, httpRequestContext);
IDictionary items = httpContextBase.Items;
if (items != null && items.Contains((object) HttpControllerHandler.OwinEnvironmentHttpContextKey))
httpRequestMessage.Properties.Add(HttpControllerHandler.OwinEnvironmentKey, items[(object) HttpControllerHandler.OwinEnvironmentHttpContextKey]);
httpRequestMessage.Properties.Add(HttpPropertyKeys.RetrieveClientCertificateDelegateKey, (object) HttpControllerHandler._retrieveClientCertificate);
httpRequestMessage.Properties.Add(HttpPropertyKeys.IsLocalKey, (object) new Lazy<bool>((Func<bool>) (() => requestBase.IsLocal)));
httpRequestMessage.Properties.Add(HttpPropertyKeys.IncludeErrorDetailKey, (object) new Lazy<bool>((Func<bool>) (() => !httpContextBase.IsCustomErrorEnabled)));
return httpRequestMessage;
}
UPDATE 2:
Inside of mvc controllers, the context is available. But not in webapi controllers.
A team mate found a solution. He simply added the following line to the owin startup class:
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
Why this solves the issue is another mystery, though. But we are using wsFederation, so I guess it's needed some how. But what if we didn't use wsFed? Would we still need it to get a context? Who knows...

Why HttpContext.Current is Static?

I am a bit confused why HttpContext.Current is a static property ? If runtime is processing more than 1 requests at the time, will not all the requests see the same value of Current ,since it is static ? or it is handled by frameworking using some synchronization technique and if it is so, why static not normal property.
Missing something ?
Here is implementation of Current property:
public static HttpContext Current
{
get
{
return ContextBase.Current as HttpContext;
}
set
{
ContextBase.Current = (object) value;
}
}
And ContextBase that used in that property:
internal class ContextBase
{
internal static object Current
{
get
{
return CallContext.HostContext;
}
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)] set
{
CallContext.HostContext = value;
}
}
And CallContext:
public sealed class CallContext
{
public static object HostContext
{
[SecurityCritical]
get
{
ExecutionContext.Reader executionContextReader =
Thread.CurrentThread.GetExecutionContextReader();
return executionContextReader.IllogicalCallContext.HostContext ?? executionContextReader.LogicalCallContext.HostContext;
}
[SecurityCritical]
set
{
ExecutionContext executionContext =
Thread.CurrentThread.GetMutableExecutionContext();
if (value is ILogicalThreadAffinative)
{
executionContext.IllogicalCallContext.HostContext = (object) null;
executionContext.LogicalCallContext.HostContext = value;
}
else
{
executionContext.IllogicalCallContext.HostContext = value;
executionContext.LogicalCallContext.HostContext = (object) null;
}
}
As you can see from the CallContext.HostContext it uses Thread.CurrentThread object, and it belongs to current thread, so it won't be shared with others threads\requests.
Sometimes you need to have access to HttpContext outside from Page\Controller. For example if you have some code that executes somewhere else, but it was triggered from Page. Then in that code you can use HttpContext.Current to get data from current request, response and all other context data.

Using simplemembership within ninject repository - via API & standard controller

I am building a fairly small sized mvc4 application. I want to use the simple membership provided as in time I can it being useful for the social stuff.
I want to be able to take advantage of the webapi within the project as I am building an ios application and would like for it to be able to use the same registration/account details. I have added an API area to the site.
I am using ninject for my injection so I have created a repository and have taken the default membership registration component and put it into this.
My Account controller and the apicontroller use the same repository.
public RegisterModel RegisterLocalUser(RegisterModel model)
{
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password,
new
{
Mobile = model.Mobile,
FirstName = model.FirstName,
LastName = model.LastName,
Email = model.Email,
});
Creating a user using the site works fine however when I try to use the api via fiddler to create a user I run into an issue of
{"Message":"An error has occurred.","ExceptionMessage":"You must call the \"WebSecurity.InitializeDatabaseConnection\" method before you call any other method of the \"WebSecurity\" class. This call should be placed in an _AppStart.cshtml file in the root of your site.","ExceptionType":"System.InvalidOperationException","StackTrace":" at WebMatrix.WebData.SimpleMembershipProvider.VerifyInitialized()\r\n at WebMatrix.WebData.WebSecurity.VerifyProvider()\r\n at WebMatrix.WebData.WebSecurity.CreateUserAndAccount(String userName, String password, Object propertyValues, Boolean requireConfirmationToken)\r\n at MySite.Web.Repository.AccountRepository.RegisterLocalUser(RegisterModel model) in c:\#Projects\Site\Site\Site.Consumer.Web\Repository\AccountRepository.cs:line 28\r\n at MySite.Web.Areas.API.Controllers.AccountController.RegisterLocal(RegisterModel data) in c:\#Projects\Site\Site\Site.Consumer.Web\Areas\API\Controllers\AccountController.cs:line 26\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c_DisplayClass13.b_c(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c_DisplayClass5.b_4()\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)"}
Adding a breakpoint within the repository the CreateUserAndAccount is never completed.
I have a custom DependancyResolver needed to allow the api and mvc stuff to work
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Has someone else been able to find a work around to get these components working together?
Thank you
Your error dump suggests you are not using the InitializeSimpleMembershipAttribute for your AccountController.
Either decorate your new account controller with InitializeSimpleMembershipAttribute or move that Websecurity.InitializeDatabaseConnection() to your Global.asax startup code.
Of course, this ignores the dependency issue and I don't have a good answer for that as I don't bother injecting WebSecurity.
WebSecurity is a static class
You'd only need to call InitializeDatabaseConnection once at startup. With the attribute usage it's called each time the controller is accessed.
Which means you must inject an initialized WebSecurity into your repository.

Entity Framework Saving User when record is Modified

When a Record gets updated in my Database, I need to be able to save who edited it.
Currently in my Repository I do this
pt.ModifiedBy = HttpContext.Current.User.Identity.Name;
There has to be a better way of doing this or is this only method?
By using HttpContext.Current.User you're tightly coupling your DbContext with HttpContext which is not a good idea in case you'll expose your DbContext to a non-web environment (UnitTesting, WCF, WPF etc).
You can use System.Security.Principal.IIdentity instead, just like exposed in ASP.NET (System.Web.HttpContext.Current.User.Identity), WCF (System.ServiceModel.OperationContext.Current.ServiceSecurityContext.PrimaryIdentity) and Thread (Thread.CurrentPrincipal.Identity).
Then, have your DbContext accept IIdentity in its constructor, and whenever the context initialized pass the appropriate IIdentity (from your current context).
For example (based on #qujck answer):
public class MyContext : DbContext
{
private readonly IIdentity _identity;
public DbContext(IIdentity identity)
{
this._identity = identity;
}
public override int SaveChanges()
{
//you may need this line depending on your exact configuration
//ChangeTracker.DetectChanges();
foreach (DbEntityEntry o in GetChangedEntries())
{
IEntity entity = o.Entity as IEntity;
entity.ModifiedBy = this._identity.Name;
}
return base.SaveChanges();
}
}
// Usage (ASP.NET):
var context = new DbContext(System.Web.HttpContext.Current.User.Identity);
IMO the best option is to handle all the auditing in one place - your unit of work (DbContext). This is easily achieved by having all of your Poco objects implement a common interface, such as IEntity.
Here's an example:
public class MyContext : DbContext
{
public override int SaveChanges()
{
//you may need this line depending on your exact configuration
//ChangeTracker.DetectChanges();
foreach (DbEntityEntry o in GetChangedEntries())
{
IEntity entity = o.Entity as IEntity;
entity.ModifiedBy = HttpContext.Current.User.Identity.Name;
}
return base.SaveChanges();
}
private IEnumerable<DbEntityEntry> GetChangedEntries()
{
return new List<DbEntityEntry>(
from e in ChangeTracker.Entries()
where e.State != System.Data.EntityState.Unchanged
select e);
}
}

The IControllerFactory 'Spring.Web.Mvc.SpringControllerFactory' did not return a controller for the name 'Account

I am getting problem like
"The IControllerFactory 'Spring.Web.Mvc.SpringControllerFactory' did not return a controller for the name 'Account'" . What does this mean?????
I am calling Logon method from controller named Account.
but when same file is kept in home controller and called then it renderes.
I had the same problem. In my case I was using Spring.NET Dependency Injection and I forgot to declare the AccountController object dependency in the XML file.
One year later, I hope this helps someone.
I think it's a bug in a Spring.NET Spring.Web.Mvc.SpringControllerFactory:
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
IController controllerInstance = null;
if (controllerType != null)
{
IDictionary objectsOfType = ApplicationContext.GetObjectsOfType(controllerType);
if (objectsOfType.Count > 0)
{
controllerInstance = (IController)objectsOfType.Cast<DictionaryEntry>().First<DictionaryEntry>().Value;
}
}
else // there should be if (contollerInstance == null)
{
controllerInstance = base.GetControllerInstance(requestContext, controllerType);
}
this.AddActionInvokerTo(controllerInstance);
return controllerInstance;
}
If controllerInstance cannot be gained from a Spring container - it should be retrieved from a base class (DefaultControllerFactory).

Resources