If I use the Universal Membership Provider and a seperate database, Entity Framework and enable Mini Profiler for EF 4.2. I get error {"There is already an object named 'Applications' in the database."} when I first hit a line checking user credentials in my home view.
If I turn remove MiniProfilerEF.Initialize(); then I stop getting the error.
Any ideas?
Can I stop profiling the defaultconnection?
I have been banging my head against this issue for awhile now. Did some more digging today and was able to get it working. Here is what I did. In MiniProfiler.cs I defined two methods as follows:
public static DbConnection GetConnection()
{
var connectionString = ConfigurationManager.ConnectionStrings["MyModelConnectionString"].ConnectionString;
var entityConnStr = new EntityConnectionStringBuilder(connectionString);
var realConnection = new SqlConnection(entityConnStr.ProviderConnectionString);
return realConnection;
}
public static IMyModelsInterface GetProfiledContext()
{
var connection = new MvcMiniProfiler.Data.EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
var context = connection.CreateObjectContext<MyModel>();
return context;
}
NOTE: These two methods probably shouldn't be defined in MinProfilerPackage, but this was my first past/hack to get it working.
Then call GetProfiledContext() and use the context returned whenever you want the queries profiled. I injected this profile context into my controller factory using Ninject. My call looks something like this:
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
private void AddBindings()
{
var context = MiniProfilerPackage.GetProfiledContext();
IUnitOfWork uow = new UnitOfWork(context);
ninjectKernel.Bind<IRepository>().To<GenericRepository>().WithConstructorArgument("paramUnitOfWork", uow);
// ... rest of the method
}
NinjectControllerFactory is my controller factory that gets set in Application_Start.
protected void Application_Start()
{
// Add in DI for controller and repo associations
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
// ... rest of the method
}
Related
I am working with ApplicationInsights, defining and sending my own custom events.
I use the telemetryclient for that.
It works only if I instantiate and use my telemetryclient object as following:
TelemetryClient telemetryClient;
using (var telemetryConfiguration = new TelemetryConfiguration("instrumentationKey"))
{
telemetryClient = new TelemetryClient(telemetryConfiguration);
telemetryClient.TrackEvent("CustomEvent1");
telemetryClient.Flush();
Thread.Sleep(5000);
}
The problem is, that I want to inject the telemtryClient in different services. Yet calling this call at the same Position generates no Events in the portal:
TelemetryClient telemetryClient;
using (var telemetryConfiguration = new TelemetryConfiguration("instrumentationKey"))
{
telemetryClient = new TelemetryClient(telemetryConfiguration);
}
telemetryClient.TrackEvent("CustomEvent1");
telemetryClient.Flush();
Thread.Sleep(5000);
Is that the wrong way to use the telemtryClient?
If you are writing a .Net Core Application you can configure dependency Injection of the TelemetryClient in the ConfigureServices method of your Startup.cs.
See here for a complete example.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddApplicationInsightsTelemetry();
...
}
Then, if you are writing a Mvc app, for example, you can inject the TelemetryClient in your controllers like this:
private readonly TelemetryClient tc;
public MyController(TelemetryClient _tc)
{
tc = _tc;
}
public HttpResponseMessage Get(int id)
{
tc.TrackEvent("CustomEvent1");
...
}
Make sure to also configure your appsettings.json correctly:
"ApplicationInsights": {
"InstrumentationKey": "..." }
Hope this helps,
Andreas
Issue
For testing, I create a new job, it just use IRepository to read data from database. The code as below:
public class TestJob : BackgroundJob<string>, ITransientDependency
{
private readonly IRepository<Product, long> _productRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public TestJob(IRepository<Product, long> productRepository,
IUnitOfWorkManager unitOfWorkManager)
{
_productRepository = productRepository;
_unitOfWorkManager = unitOfWorkManager;
}
public override void Execute(string args)
{
var task = _productRepository.GetAll().ToListAsync();
var items = task.Result;
Debug.WriteLine("test db connection");
}
}
Then I create a new application service to trigger the job. The code snippet as below:
public async Task UowInJobTest()
{
await _backgroundJobManager.EnqueueAsync<TestJob, string>("aaaa");
}
When I test the job, It will throw following exception when execute var task = _productRepository.GetAll().ToListAsync();
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.Object name: 'AbpExampleDbContext'.
Solution
S1: Add UnitOfWork attribute on execute method. It can address the issue. But it is not better for my actual scenario. In my actual scenario, the job is a long time task, and has much DB operatons, if enable UnitOfWork for Execute method, it will lock db resource for a long time. So this is not a solution for my scenario.
[UnitOfWork]
public override void Execute(string args)
{
var task = _productRepository.GetAll().ToListAsync();
var items = task.Result;
Debug.WriteLine("test db connection");
}
S2: Execute DB operation in UnitOfWork explicitly. Also, this can address the issue, but I don’t think this is a best practice. In my example,just read data from database, no transaction is required. Even-though the issue is addressed, but I don’t think it’s a correct way.
public override void Execute(string args)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
var task = _productRepository.GetAll().ToListAsync();
var items = task.Result;
unitOfWork.Complete();
}
Debug.WriteLine("test db connection");
}
Question
My question is what’s the correct and best way to execute a DB operation in BackgroundJob?
There is addtional another question, I create a new application service, and disable UnitOfWrok, but it works fine. Please see the code as below. Why It works fine in application service, but doesn’t work in BackgroundJob?
[UnitOfWork(IsDisabled =true)]
public async Task<GetAllProductsOutput> GetAllProducts()
{
var result = await _productRepository.GetAllListAsync();
var itemDtos = ObjectMapper.Map<List<ProductDto>>(result);
return new GetAllProductsOutput()
{
Items = itemDtos
};
}
The documentation on Background Jobs And Workers uses [UnitOfWork] attribute.
S1: Add UnitOfWork attribute on execute method. It can address the issue. But it is not better for my actual scenario. In my actual scenario, the job is a long time task, and has much DB operatons, if enable UnitOfWork for Execute method, it will lock db resource for a long time. So this is not a solution for my scenario.
Background jobs are run synchronously on a background thread, so this concern is unfounded.
S2: Execute DB operation in UnitOfWork explicitly. Also, this can address the issue, but I don’t think this is a best practice. In my example,just read data from database, no transaction is required. Even-though the issue is addressed, but I don’t think it’s a correct way.
You can use a Non-Transactional Unit Of Work:
[UnitOfWork(isTransactional: false)]
public override void Execute(string args)
{
var task = _productRepository.GetAll().ToListAsync();
var items = task.Result;
}
You can use IUnitOfWorkManager:
public override void Execute(string args)
{
using (var unitOfWork = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress))
{
var task = _productRepository.GetAll().ToListAsync();
var items = task.Result;
unitOfWork.Complete();
}
}
You can also use AsyncHelper:
[UnitOfWork(isTransactional: false)]
public override void Execute(string args)
{
var items = AsyncHelper.RunSync(() => _productRepository.GetAll().ToListAsync());
}
Conventional Unit Of Work Methods
I create a new application service, and disable UnitOfWork, but it works fine.
Why it works fine in application service, but doesn’t work in BackgroundJob?
[UnitOfWork(IsDisabled = true)]
public async Task<GetAllProductsOutput> GetAllProducts()
{
var result = await _productRepository.GetAllListAsync();
var itemDtos = ObjectMapper.Map<List<ProductDto>>(result);
return new GetAllProductsOutput
{
Items = itemDtos
};
}
You are using different methods: GetAllListAsync() vs GetAll().ToListAsync()
Repository methods are Conventional Unit Of Work Methods, but ToListAsync() isn't one.
From the documentation on About IQueryable<T>:
When you call GetAll() outside of a repository method, there must be an open database connection. This is because of the deferred execution of IQueryable<T>. It does not perform a database query unless you call the ToList() method or use the IQueryable<T> in a foreach loop (or somehow access the queried items). So when you call the ToList() method, the database connection must be alive.
I have created an application using MVC5 with the onion architecture approach. The solution contains 3 projects (core, infrastructure, and UI). The UI contains both Web API controllers and MVC controllers. The issue I’m running into is dependency injection. I have installed Unity.MVC5 & Unity.WebApi. My UnityConfig.cs under App_Start Looks like this:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IPricingService, PricingService>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
My global.asax looks like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
System.Web.Http.GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
UnityConfig.RegisterComponents();
}
To test out my controller, I defined my home controller like this:
private readonly IPricingService _pricingService;
public HomeController(IPricingService PricingService)
{
this._pricingService = PricingService;
}
When running home page I get
No parameterless constructor defined for this object.
Now, moving to another test scenario, I created a web api controller and looks like this:
private readonly IPricingService _pricingService;
public TestApiController(IPricingService PricingService)
{
this._pricingService = PricingService;
}
Testing the web api generates this error:
An error occurred when trying to create a controller of type 'TextApiController'. Make sure that the controller has a parameterless public constructor.","exceptionType":"System.InvalidOperationException"
Not sure what I'm missing. Please advise.
You are supposed to inject the Unity.WebApi.DependencyResolver into the WebApi configuration not in GlobalConfiguration.Configuration.DependencyResolver.
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Other Web API configuration not shown.
}
You also need to implement a child container in the BeginScope method as shown in this MSDN article.
After reading questions and articles about using autofac with owin and webapi, I came across a solution to inject services but it does not work. Here is my code:
public class StartUp
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
var builder = new ContainerBuilder(); // Create the container builder.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); // Register the Web API controllers.
var authcontext = new AuthContext();
builder.RegisterInstance(authcontext).AsSelf().SingleInstance();
//Updated
//var simpleauth = new SimpleAuthorizationServerProvider();
//Updated
// builder.RegisterInstance(simpleauth).SingleInstance().AsSelf().PropertiesAutowired();
builder.Register(x => new UserStore<IdentityUser>(authcontext)).As<IUserStore<IdentityUser>>();
//updated
builder.Register(x =>
{
var p = new SimpleAuthorizationServerProvider();
var userStore = x.Resolve<IUserStore<IdentityUser>>();
p.userManager = new UserManager<IdentityUser>(userStore);
return p;
}).AsSelf().PropertiesAutowired();
builder.RegisterType<AuthRepository>().As<IAuthRepository>().InstancePerRequest().PropertiesAutowired();
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container); // Create an assign a dependency resolver for Web API to use.
config.DependencyResolver = resolver;
app.UseAutofacMiddleware(container);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
ConfigureOAuth(app, resolver);
}
public void ConfigureOAuth(IAppBuilder app, AutofacWebApiDependencyResolver resolver)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
//updated
Provider = new SimpleAuthorizationServerProvider()
//resolver.GetService(typeof(SimpleAuthorizationServerProvider)) as SimpleAuthorizationServerProvider
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
But in SimpleAuthorizationServerProvider class, when a method like ValidateClientAuthentication is begin called, all the services are null, here is the code:
public readonly IAuthRepository repository;
public readonly UserManager<IdentityUser> userManager;
public readonly AuthContext dbContext;
public SimpleAuthorizationServerProvider()
{
}
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetFormCredentials(out clientId, out clientSecret))
{
try
{
Client client = await repository.FindClientById(clientId);
}
}
}
Would you help me please ?
Updated
If in ConfigureOAuth method I use the following approach:
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = resolver.GetService(typeof(SimpleAuthorizationServerProvider)) as SimpleAuthorizationServerProvider
};
I get error:
An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code
Additional information: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
When you register an instance of an object rather than a type, even if you specify PropertiesAutowired that will not take effect because Autofac assumes you've done all the work you want when you create the instance. If you want properties wired in, you need to do that in an OnActivated handler.
There are actually a lot of things at play in this sample code that will not work.
The values in SimpleAuthorizationServerProvider are fields not properties so PropertiesAutowired won't work on them.
The fields are marked readonly and they're never set.
You have UserManager<IdentityUser> registered as a lambda but also have PropertiesAutowired which won't work - you can only use PropertiesAutowired on a reflection-based component (e.g., RegisterType<T>).
Consider registering a lambda for your provider and set everything in the lambda:
builder.Register(c => {
var p = new SimpleAuthorizationServerProvider();
p.repository = c.Resolve<UserManager<IdentityUser>>();
// ...and so on
return p;
}).AsSelf().SingleInstance();
Also, keep in mind that if you register an instance (or register something as SingleInstance the properties will be resolved one time and that's it. So if you have some dependencies that are InstancePerDependency or InstancePerRequest, that's not going to work the way you think - they'll be resolved one time and effectively be singletons after that.
Update 1
Based on the original and updated code, it occurs to me that it would be good if you could check out some of the Autofac doc to understand better how it works. For example, the use of fields in SimpleAuthorizationServerProvider shows you may not totally get how injection works in Autofac or how to properly register things so Autofac can do the work for you.
Registration concepts
Web API integration
Working with per-request lifetime
For example, looking at the updates...
You now have a lambda registered for the SimpleAuthorizationServerProvider but I don't see where you set the repository field there.
You don't need PropertiesAutowired on the SimpleAuthorizationServerProvider registration because you're registering a lambda and the properties will not be autowired (as noted earlier).
The only component I see as being registered InstancePerRequest is the AuthRepository but, like I said, I don't see where that's being resolved or set - and that's the only thing that would generate the exception you noted. There is an FAQ on dealing with that exact exception that you should look into.
Also, you are showing two different versions of the OAuthServerOptions being initialized and it's hard to tell which one is "real."
I would recommend a fairly major refactoring to enable things to actually use DI correctly.
Change the SimpleAuthorizationServerProvider to stop using public fields and add them as constructor parameters so Autofac can wire the stuff up for you.
public class SimpleAuthorizationServerProvider
{
public IAuthRepository Repository { get; private set; }
public UserManager<IdentityUser> UserManager {get; private set; }
public AuthContext Context { get; private set; }
public SimpleAuthorizationServerProvider(
IAuthRepository repository,
UserManager<IdentityUser> userManager,
AuthContext context)
{
this.Repository = repository;
this.UserManager = userManager;
this.AuthContext = context;
}
}
During startup, fix your registrations to remove extraneous stuff and take advantage of the Autofac auto-wiring goodness.
public class StartUp
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register the auth context instance but skip
// the extra .AsSelf() and .SingleInstance() because
// it's implicit.
builder.RegisterInstance(new AuthContext());
// Use the lambda to resolve the auth context rather
// than making a closure over an instance.
builder.Register(c => new UserStore<IdentityUser>(c.Resolve<AuthContext>()))
.As<IUserStore<IdentityUser>>();
// Just register the provider type and let Autofac
// do the work without all this manual stuff. Skip
// the .AsSelf() because it's implicit if you don't
// specify other interfaces and don't auto-wire properties
// because you don't need it.
builder.RegisterType<SimpleAuthorizationProvider>();
// This is fine, but I can't tell where it's used - if
// you are using it at app startup or OUTSIDE a request,
// you will get that exception you noted. Also, unless
// you're actually using property injection, lose the
// .PropertiesAutowired() call.
builder.RegisterType<AuthRepository>()
.As<IAuthRepository>()
.InstancePerRequest()
.PropertiesAutowired();
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
app.UseAutofacMiddleware(container);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
ConfigureOAuth(app, resolver);
}
public void ConfigureOAuth(IAppBuilder app, AutofacWebApiDependencyResolver resolver)
{
var options = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
// If you want the values to be wired up, you have
// to do a resolve. Note, however, that since you're
// doing this wire-up at app startup, there's no request
// scope, so if something in here is registered `InstancePerRequest`
// you will get an exception.
Provider = resolver.GetService(typeof(SimpleAuthorizationServerProvider)) as SimpleAuthorizationServerProvider
};
app.UseOAuthAuthorizationServer(options);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
Under the assumption that's all the code you should be OK. If things aren't set - like one of the SimpleAuthorizationServerProvider properties comes through as null, or if you get an exception because it's missing a dependency, or if you get the exception about there being no request scope... then there's something else going on that you haven't put in your question.
Again, please take the time to check out the docs and familiarize yourself with Autofac. I think many of the troubles you're running into are the result of some misunderstanding on how things get wired up.
In a console application, I would like to use a service that would normally need the current http context to be passed to its constructor. I am using Ninject, and I think I can simply fake an http context and define the proper binding, but I have been struggling with this for a few hours without success.
The details:
The service is actually a mailing service that comes from an ASP.Net MVC project. I am also using Ninject for IoC. The mail service needs the current http context to be passed to its constructor. I do the binding as follows:
kernel.Bind<IMyEmailService>().To<MyEmailService>()
.WithConstructorArgument("httpContext", ninjectContext => new HttpContextWrapper(HttpContext.Current));
However, I would like now to use this mailing service in a console application that will be used to run automated tasks at night. In order to do this, I think I can simply fake an http context, but I have been struggling for a few hours with this.
All the mailing service needs from the context are these two properties:
httpContext.Request.UserHostAddress
httpContext.Request.RawUrl
I thought I could do something like this, but:
Define my own fake request class:
public class AutomatedTaskHttpRequest : SimpleWorkerRequest
{
public string UserHostAddress;
public string RawUrl;
public AutomatedTaskHttpRequest(string appVirtualDir, string appPhysicalDir, string page, string query, TextWriter output)
: base(appVirtualDir, appPhysicalDir, page, query, output)
{
this.UserHostAddress = "127.0.0.1";
this.RawUrl = null;
}
}
Define my own context class:
public class AutomatedTasksHttpContext
{
public AutomatedTaskHttpRequest Request;
public AutomatedTasksHttpContext()
{
this.Request = new AutomatedTaskHttpRequest("", "", "", null, new StringWriter());
}
}
and bind it as follows in my console application:
kernel.Bind<IUpDirEmailService>().To<UpDirEmailService>()
.WithConstructorArgument("httpContext", ninjectContext => new AutomatedTasksHttpContext());
Unfortunately, this is not working out. I tried various variants, but none was working. Please bear with me. All that IoC stuff is quite new to me.
I'd answered recently about using a HttpContextFactory for testing, which takes a different approach equally to a console application.
public static class HttpContextFactory
{
[ThreadStatic]
private static HttpContextBase _serviceHttpContext;
public static void SetHttpContext(HttpContextBase httpContextBase)
{
_serviceHttpContext = httpContextBase;
}
public static HttpContextBase GetHttpContext()
{
if (_serviceHttpContext!= null)
{
return _serviceHttpContext;
}
if (HttpContext.Current != null)
{
return new HttpContextWrapper(HttpContext.Current);
}
return null;
}
}
then in your code to this:
var rawUrl = HttpContextFactory.GetHttpContext().Request.RawUrl;
then in your tests use the property as a seam
HttpContextFactory.SetHttpContext(HttpMocks.HttpContext());
where HttpMocks has the following and would be adjusted for your tests:
public static HttpContextBase HttpContext()
{
var context = MockRepository.GenerateMock<HttpContextBase>();
context.Stub(r => r.Request).Return(HttpRequest());
// and stub out whatever else you need to, like session etc
return context;
}
public static HttpRequestBase HttpRequest()
{
var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
httpRequest.Stub(r => r.UserHostAddress).Return("127.0.0.1");
httpRequest.Stub(r => r.RawUrl).Return(null);
return httpRequest;
}