Unity crashes Web API, no log - asp.net

I want to place my HTML parser into a singleton instance, so I utilized Unity to create and hold my class. Unfortunately this causes the app crash, and I have no information about the error.
I have Elmah but no entry in the datatable.
My bits are:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Filters.Add(new ElmahErrorAttribute());
UnityConfig.RegisterComponents();
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}
Controller:
public class AccountsController : BaseApiController
{
private readonly ITemplateService _templateService;
public AccountsController() { }
public AccountsController(ITemplateService templateService)
{
_templateService = templateService;
}
UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITemplateService, TemplateService>(new ContainerControlledLifetimeManager());
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
No log, no place to set up a breakpoint where the error is, app is crashing.

There is always a log in the EventViewer
Open it and there you find what is crash your program.

Related

.net 6.0 Integration tests

I have a problem that I can`t create HttpClient for integration tests.
I have ready carefully this article:
https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0
Microsoft.AspNetCore.Mvc.Testing installed
<Project Sdk="Microsoft.NET.Sdk.Web"> in csproj
CustomWebApplicationFactory:
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
Environment.SetEnvironmentVariable("HANGFIRE_DASHBOARD_USERNAME", "test");
Environment.SetEnvironmentVariable("HANGFIRE_DASHBOARD_PASSWORD", "test");
Environment.SetEnvironmentVariable("ASPNETCORE_URLS", "https://+:1229");
base.ConfigureWebHost(builder);
}
}
ControllerIntegrationTests:
public class ControllerIntegrationTests : IClassFixture<CustomWebApplicationFactory<Startup>>
{
private readonly HttpClient client;
private readonly CustomWebApplicationFactory<Startup> factory;
public ControllerIntegrationTests(CustomWebApplicationFactory<Startup> factory)
{
this.factory = factory;
client = this.factory.CreateClient();
}
[Fact]
public async Task TestGetEndpointReturnSuccess()
{
// Arrange
// Act
var response = await client.GetAsync("/Information");
// Assert
response.EnsureSuccessStatusCode();
}
}
Nothing special in my code, just a simple example. As a result in Output I have :
Hosting environment:Development
Now listening on : https://[::]:1229
Application started. Press Ctrl+C to shut down.
It seems like it started the main application. And I cant move to Act in test, because its hanging in CreateClient(). So I can`t finish my test. Whats wrong?
You forget in your CustomWebApplicationFactory to override the CreateHostBuilder.
protected override IHostBuilder CreateHostBuilder()
{
return Host.CreateDefaultBuilder().ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<TStartup>();
});
}
Try to add this method in your Factory class using the TStartup.

Controller constructor does not get called

Hello i am trying to understand why do my requests not enter my api route.They seem to reach the server but they wont fan out in the MVC.
The server is running on: http://localhost:9300
The route i am requesting is : http://localhost:9300/api/getusers
Program
public class Program {
public static void Main(string[] args) {
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) {
var builder = new WebHostBuilder();
builder.UseStartup<Startup>();
var url = Address.Default.ToUrl();
builder.UseKestrel().UseUrls(url);
return builder;
}
}
Startup
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services) {
services.AddOptions();
services.AddMvc();
}
public IConfiguration Configuration;
public void Configure(IApplicationBuilder app) {
Debug.WriteLine("Entered server"); //enters successfully here
app.UseMvc(); //does not enter the controller
}
}
Controller
This is a simple controller with a GET method.The constructor is not invoked at all.Why would this happen?I know it when the server runs the first time ..it does a health check on its routes.
[ApiController]
class UserController : ControllerBase {
private static List<User> users = new List<User> {
new User{Id=0,Age=0,Name="Failed"},
new User{Id=12,Age=33,Name="Daniel"},
new User{Id=13,Age=33,Name="Marian"},
};
public UserController() {
Debug.WriteLine("Controller called"); //does not get called !
}
[HttpGet]
[Route("api/getusers")]
public async Task<HttpResponseMessage> GetUsers() {
await Task.Delay(1000);
return new HttpResponseMessage {
Content = new StringContent(users.ToJson()),
StatusCode = HttpStatusCode.OK
};
}
}
P.S Do i have to add anyything ? What am i missing i followed other implementations closely.
I've created the webapi project using dotnet new webapi.
I've managed to get to the url with the similar configuration by changing the access modifier of a similar controller. Try to add public keyword to the class UserController. So it should be public class UserController
I will provide more information about the configuration of the project if it is necessary and the step above does not help.

Why is the identity not loaded when resolving WebApi but is when resolving Mvc controllers

I am using Autofac for an Inversion of Control container which is configured like this
public void Configuration(IAppBuilder app) {
configureIoC(app);
configureAuth(app);
}
void configureIoC(IAppBuilder app) {
var b = new ContainerBuilder();
//...
b.Register(c => HttpContext.Current?.User?.Identity
?? new NullIdentity()).InstancePerLifetimeScope();
var container = b.Build();
app.UseAutofacMiddleware(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
I believe the fact that this is Autofac versus some other container is probably irrelevant to what I'm seing. They key line here is the one configuring any dependency on IIdentity to be plucked from HttpContext.Current.
I use it like this so that I can have stub-able access to the current user anywhere I want.
public interface ICurrentUser {
Task<AppUser> Get();
}
public class CurrentUserProvider : ICurrentUser {
public async Task<AppUser> Get() => await users.FindByNameAsync(currentLogin.GetUserId());
public CurrentUserProvider(AppUserManager users, IIdentity currentLogin) {
this.users = users;
this.currentLogin = currentLogin;
}
}
I've used this pattern on past projects and it works fine. I'm currently applying it to an existing project and seeing a very strange thing.
When an Asp.net Mvc controller depends on ICurrentUser everything works fine
When a WebApi controller gets an instance of ICurrentUser the Get operation fails since the instance of IIdentity has not been parsed from the cookie and does not yet have Claims loaded into it (AuthenticationType == null)! Oddly, if I pause the debugger after the WebApi controller is instantiated I can hit HttpContext.Current.User.Identity and see that AuthenticationType == "Cookie" and all claims are there.
What this leads me to conclude is that somehow things are happening in the following order
If this is a web api route, the Web Api controller creates an instance
Asp.Net Identity fills out the current HttpContext Identity
If this is an mvc route, the mvc controller creates an instance
Any actions are executed
This of course makes no sense at all!
So the questions are as follows
Is my inference of the order of things in the pipeline correct?
How can I control it to work properly? Why would this have worked on other projects but be causing problems here? Am I wiring something up in the wrong order?
Please don't suggest that I create an IdentityProvider to late-resolve IIdentity. I understand how I can fix the issue, what I don't understand is why this is happening to begin with and how to control the pipeline order of things.
I modified your code just a little, since I don't have NullIdentity() and your CurrentUserProvider wasn't compiling here.
I'm installed these packages:
Autofac
Autofac.Owin
Autofac.Owin
Autofac.Mvc5
Autofac.Mvc5.Owin
Autofac.WebApi2
Autofac.WebApi2.Owin
My Startup.cs looks like this:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
configureIoC(app);
ConfigureAuth(app);
}
void configureIoC(IAppBuilder app) {
var b = new ContainerBuilder();
//...
b.RegisterType<CurrentUserProvider>().As <ICurrentUser>().InstancePerLifetimeScope();
b.Register(c => HttpContext.Current.User.Identity).InstancePerLifetimeScope();
b.RegisterControllers(typeof(MvcApplication).Assembly);
b.RegisterApiControllers(typeof(MvcApplication).Assembly);
var x = new ApplicationDbContext();
b.Register<ApplicationDbContext>(c => x).InstancePerLifetimeScope();
b.Register<UserStore<ApplicationUser>>(c => new UserStore<ApplicationUser>(x)).AsImplementedInterfaces().InstancePerLifetimeScope();
b.RegisterType<ApplicationUserManager>().InstancePerLifetimeScope();
b.RegisterType<ApplicationSignInManager>().InstancePerLifetimeScope();
var container = b.Build();
app.UseAutofacMiddleware(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
Your ICurrentUser stuff:
public interface ICurrentUser
{
Task <ApplicationUser> Get();
}
public class CurrentUserProvider : ICurrentUser
{
private ApplicationUserManager users;
private IIdentity currentLogin;
public async Task<ApplicationUser> Get()
{
return await users.FindByNameAsync(currentLogin.GetUserId());
}
public CurrentUserProvider(ApplicationUserManager users, IIdentity currentLogin)
{
this.users = users;
this.currentLogin = currentLogin;
}
}
Therefore Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
My HomeController which is quite simple:
public class HomeController : Controller
{
private ICurrentUser current;
public HomeController(ICurrentUser current)
{
this.current = current;
}
public ActionResult Index()
{
var user = current.Get();
if (user == null)
throw new Exception("user is null");
return View();
}
}
...and finally a simple ApiController, which I access by typing localhost/api/TestApi/5:
public class TestApiController : ApiController
{
private ICurrentUser current;
public TestApiController(ICurrentUser current)
{
this.current = current;
}
public string Get(int id)
{
var user = current.Get();
if (user == null)
throw new Exception("user is null");
return "";
}
}
If I just start the project (without even logging in), I receive a GenericIdentity object to support IIdentity interface, look at this:
And when I step in (F11) in the Get() method, the IIdentity is properly set with that GenericIdentity, because actually there is no one Logged in the application. That's why I think you don't actually need that NullableIdentity.
Try comparing your code with mine and fix yours so we can see if it works, then eventually you'll find out what was the real cause of the problem, rather than just fixing it (we developers like to know why something just got working).

Unity injection into asp.net web api controllers and filters

I have WebForms project, and there I have WebApi controller.
How I can inject to controller constructor and to action filter constructor?
I have implemented IDependencyResolver and use it in Global.asax (GlobalConfiguration.Configuration.DependencyResolver), but it doesn't help:
on request controller says that there is no default constructor and filter on application start says that it does not contain a constructor that takes 0 arguments.
Moreover, i need singletone injection to action filter.
Thanks.
UPD
public class ScopeContainer : IDependencyScope
{
protected readonly IUnityContainer _container;
public ScopeContainer(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.ResolveAll(serviceType) : new List<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
public class IoCContainer : ScopeContainer, IDependencyResolver
{
public IoCContainer(IUnityContainer container) : base(container)
{
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new ScopeContainer(child);
}
}
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterInstance<ILogger>(new Logger());
unity.RegisterType<IRepository, DbRepository>();
config.DependencyResolver = new IoCContainer(unity);
}
private static void RegisterRoutes()
{
RouteTable.Routes.MapHttpRoute("ServiceApi", "api/{controller}/{action}");
}
}
I think this may be the way you are registering your routes.
WebApi routes are registered in the default project examples via the GlobalConfiguration.Routes rather than the RouteTable.Routes which is used by MVC controllers. If the ApiController is being incorrectly loaded by the MVC routing method it won't find your dependency resolver.
Try modifying your code to this:
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(GlobalConfiguration.Configuration);
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterInstance<ILogger>(new Logger());
unity.RegisterType<IRepository, DbRepository>();
config.DependencyResolver = new IoCContainer(unity);
}
private static void RegisterRoutes(HttpConfiguration config)
{
config.Routes.MapHttpRoute("ServiceApi", "api/{controller}/{action}");
}
}
I was having the same issue, I was working on a project trying to help modernize an old web forms project by converting page by page to Web API / Angular and getting the plumbing just right to use Unity was key.
When I was tracing I noticed unity was trying to resolve the controller classes but not the types to inject into their constructors, so I registered my controllers and it all worked. See my example below
Config setup, register controller and dependency
void ConfigureApi(HttpConfiguration config)
{
var container = UnitySingleton.UnityContainer;
container.RegisterType<IDashboardManager, ExampleStuff>();
container.RegisterType<DashboardController>(new InjectionConstructor(container.Resolve<IDashboardManager>()));
config.DependencyResolver = new UnityIoCContainer(container);
}
And my controller example:
public class DashboardController : ApiController
{
private readonly IDashboardManager _dashboardManager;
public DashboardController(IDashboardManager dashboardManager)
{
_dashboardManager = dashboardManager;
}
public async Task<IEnumerable<string>> Get()
{
return await _dashboardManager.GetDatas();
}
}
This is how I got mine working. It was a little different than the article above.

NullReferenceExpection in a Integration test project for an asp.net nhibernate solution

i have a .NET 3.5 solution with an asp.net(web site) project with fluentnhibernate and it's test project(class library project).i've referenced the asp.net project in the test project and with all fluentnhibernate/nhibenate dlls.
What i fail to comprehend is that, on a run of a webform (hit from browser) let's say Test.aspx, building of schema is successfull and i could see the tables in my database.
here is the method i call on Test.aspx.cs
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ISession session = SessionManager.Instance.OpenSession();
SessionManager.BuildSchema(session);
}
}
i happen to use the same method in CanGenerateSchema method of my test class and it always fails
[TestFixture]
public class CanGenerateSchemaTestSuite
{
[Test]
public void CanGenarateSchema()
{
ISession session = SessionManager.Instance.OpenSession();
SessionManager.BuildSchema(session);
}
}
here is the SessionManager i use :
public sealed class SessionManager
{
private readonly ISessionFactory _sessionFactory;
public static ISessionFactory SessionFactory
{
get { return Instance._sessionFactory; }
}
private ISessionFactory GetSessionFactory()
{
return _sessionFactory;
}
public static SessionManager Instance
{
get { return NestedSessionManager._sessionManager; }
}
public ISession OpenSession()
{
return Instance.GetSessionFactory().OpenSession();
}
private static Configuration SaveConfigs;
private SessionManager()
{
try
{
if (_sessionFactory == null)
{
//from the debugging the code breaks from here when trying to get connectionstring.
string constring = ConfigurationManager.AppSettings["localdb"].ToString();
FluentConfiguration configuration = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(constring))
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<myproject.model.Request>();
m.FluentMappings.AddFromAssemblyOf<myproject.model.Route>();
})
.ExposeConfiguration((x) =>
{
SaveConfigs = x;
x.SetProperty("current_session_context_class", "thread_static");
});
_sessionFactory = configuration.BuildSessionFactory();
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
}
public static void BuildSchema(ISession session)
{
var export = new SchemaExport(SaveConfigs);
export.Execute(false,true,false,session.Connection,null);
}
class NestedSessionManager
{
internal static readonly SessionManager _sessionManager = new SessionManager();
}
}
So from my comment the NullReferenceException happens when accessing the connectionstring. I don't have the explanation on why that happens.I'm sure it's some kind of gotchas, i can't get over it.I would be very grateful if anyone could give me a hand here.thanks for reading.
ConfigurationManager.AppSettings["localdb"] from Test.aspx would be pulling from your web.config file on a web project.
That file wouldn't be accessible to your test project (I'm assuming your tests are in a separate project from your web site). You should be able to get around this by adding an app.config file into your test project with the correct localdb settings or rather than using a configuration string, use FluentNHibernate's fluent builder.
Example app.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="localdb" value="yourconnectionstring" />
</appSettings>
</configuration>
If the value returned by ConfigurationManager.AppSettings["localdb"] is null then the .ToString() call will cause the NullReferenceException.
Ensure the "localdb" setting exists.

Resources