Initializing ASP.NET Web application on application pool start - asp.net

I have searched the web for over one day but I did not find anything I need.
I am developing an IIS web application with HttpHandlers and HttpModules. I need to initialize the application on first run (applying configuration). But I do not want to use global.asax.cs because I do not want implementations having a global.asax file in their folder (a web.config at most).
How do I run some code when the application pool is being initialized?

You could use the assembly level attribute PreApplicationStartMethodAttribute to have your startup code run early in the ASP.NET pipeline.
namespace MyWebService
{
public class MyHttpHandler: IHttpHandler, IDisposable
{
public static void StartUp()
{
//Application Startup Code;
}
public void ProcessRequest(HttpContext context)
{
//Do Something
}
public bool IsReusable { get; private set; }
public void Dispose(){};
}
}
}
}
And add the attribute to your AssemblyInfo.cs
[assembly: PreApplicationStartMethod(typeof(MyWebService.MyHttpHandler), "StartUp")]
For more info on PreApplicationStartMethod : https://msdn.microsoft.com/en-us/library/system.web.preapplicationstartmethodattribute

Related

ASP .NET Core Publish Errors AddDbContext

i actually dont know deploy IIS for LAN server. We are working on this project together with my friend. We share same Wifi. So we want shared api project. Because i working on backend (API-DAL-BLL) layers, my friends working on FrontEnd. But i cant deploy very well.
First my publish cant see my DBContext.So i added Startup addDbContext.
My Startup.cs like this
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GastroDB>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IMainCategoryService, MainCategoryService>();
}
My Program.cs like this
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel().UseContentRoot(Directory.GetCurrentDirectory()).UseUrls("myIpAdress:80").UseIISIntegration().UseStartup<Startup>();
});
}
But iis can not get start. This is my errors ;
.Net Runtime:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ArgumentException: 'AddDbContext' was called with configuration, but the context type 'GastroDB' only declares a parameterless constructor. This means that the configuration passed to 'AddDbContext' will never be used. If configuration is passed to 'AddDbContext', then 'GastroDB' should declare a constructor that accepts a DbContextOptions<GastroDB> and must pass it to the base constructor for DbContext.
2)IIS AspNetCore Module V2
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\Users\Tuğçe\Desktop\almanya projesi BE\EcommerceGastro.API\bin\Release\net5.0\publish\' hit unexpected managed exception, exception code = '0xe0434352'. First 30KB characters of captured stdout and stderr logs:
Unhandled exception. System.ArgumentException: 'AddDbContext' was called with configuration, but the context type 'GastroDB' only declares a parameterless constructor. This means that the configuration passed to 'AddDbContext' will never be used. If configuration is passed to 'AddDbContext', then 'GastroDB' should declare a constructor that accepts a DbContextOptions<GastroDB> and must pass it to the base constructor for DbContext.
I understand i will shoul add my context constructor like this
public GastroDB(DbContextOptions<GastroDB> options):base(options){}
But i cant add because first start like that on DBContext:
public class GastroDB : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.; database=GastroDB; user id=sa; password=123;");
}
private static GastroDB _dbInstance;
public static GastroDB DBInstance
{
get
{
if (_dbInstance == null)
{
_dbInstance = new GastroDB();
}
return _dbInstance;
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new MyMap());
...
}
public DbSet<MyClass> MyClass{ get; set; }
....
}
}
If i add ctor on this code, my some services throw exeption because i use like this
using (var transaction = new GastroDB())
{
var productList = transaction.Set<DBProduct>().Include(x => x.ProductImage).ToList();
return this.mapper.Map<List<Product>>(productList);
}
How can i fix this problems i dont know how. Please help me
You Should create a constructor that accept
DbContextOptions<GastroDB>.
You don't need to use public static GastroDB DBInstance because
DbContext are registerd as Scoped life time.
public class GastroDB : DbContext
{
public GastroDB(DbContextOptions<GastroDB> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.; database=GastroDB; user id=sa; password=123;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new MyMap());
...
}
public DbSet<MyClass> MyClass{ get; set; }
....
}
}
3 . If you want your DbContext register as singleton lifetime you can use below code instead of create a static property in DbContext
services.AddDbContext<GastroDB>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
}, ServiceLifetime.Singleton);

Controller not found within a Web forms application

I have a project where there is a controller within a web forms application.
My controller is called Token
public class TokenController : BaseTokenController
{
public override bool IsInherited => true;
}
this controller inherits from BaseTokenController
public abstract class BaseTokenController : ApiController
{
public abstract bool IsInherited { get; }
public virtual bool Post([FromBody]TokenValidateArgs args)
{
if (!IsInherited)
throw new Exception("Attempt to call base token controller not allowed");
return args.Validate();
}
public virtual string Get()
{
if (!IsInherited)
throw new Exception("Attempt to call base token controller not allowed");
return new Token()
}
}
In my global.asax I have a method called Register:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("API default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
}
and in global.asax Application_Start the first line of code is
protected void Application_Start(object sender, EventArgs e)
{
Register(GlobalConfiguration.Configuration);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I did have this working, however I then merged with the master branch for the project and it stopped working. I can't see anything that has changed.
this is the error:
No HTTP resource was found that matches the request URI 'https://localhost:44398/api/token'.
No type was found that matches the controller named 'token'.
Has anyone else experienced a similar issue and would know how to fix this. I have read other threads and tried to fix this by putting in a RoutePrefix on the controller, moving the order of execution on the global.asax and calling the get() method directly
So for my issue it turns out the project that has the "BaseTokenController" was running version 5.2.3 of WebApi however the web application project was running 5.2.4 which caused a conflict, resulting in a 404 error. To fix this I downgraded the app to 5.2.3

asp.net core web api, how to inject the connection string

Here is my asp.net core project structure
1- ASP.NET CORE Web API (contains aspsettings.json)
"ConnectionStrings": {
"DefaultConnection": "Server=(local)\\SQLEXPRESS;Database=testdb;Trusted_Connection=True;"
}
2-SERVICES Project (Web API Call method from Services Project)
3-REPOSITORY Project (Services call method from Repository Project and Repository Project include the DATA Project where all the models are)
4-DATA Project where it's contain all the model with code first
public class TtEntities : DbContext
{
public virtual DbSet<RoomMessage> RoomMessage { get; set; }
public virtual DbSet<UserRoom> UserRoom { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=(local)\SQLEXPRESS;Database=testdb;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
As you can see, I hardcoded the connection on the method OnConfiguring which is not the best practice for sure.
Is there a way to pass the connection string from the configuration file of the Web API Project?
Is update database command will still work if we pass the connection from the file aspsettings.json from web api project ?
Thanks a lot
A simple solution is like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
}
Consider how DefaultConnection is used in line 13. Also a sample appsettings is like as follow:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplication5;"
}
}
DI solves this problem perfectly and .NET Core 2.0 has Microsoft DI thats provides clearly experience with DI.
oh, lets starts(i think that DATA Project and REPOSITORY Project should be one)
from REPOSITORY Project
change your REPOSITORYClass to
public class REPOSITORYClass
{
private readonly TtEntities _db;
public REPOSITORYClass (TtEntities db){
_db = db;
}
//some your staff of REPOSITORYClass thats uses _db
}
now go to SERVICES Project
lets change some service that uses REPOSITORYClass
public class SomeService
{
private readonly REPOSITORYClass _repo;
public SomeService (REPOSITORYClass repo){
_repo = repo;
}
//other staff of SomeService thats uses _repo
}
after that go to ASP.NET CORE Web API startup file and add to
public void ConfigureServices
// Get connection of your repo
string connection = Configuration.GetConnectionString("DefaultConnection");
// add TtEntities as service
services.AddDbContext<TtEntities>(options =>
options.UseSqlServer(connection));
//add your repo
services.AddTransient<REPOSITORYClass>();
//add your service
services.AddTransient<SomeService>();
now go to the contoller thats uses your SomeService
public class SomeController: Controller
{
private readonly SomeService _someService;
public SomeController(SomeService someService){
_someService = someService;
}
//And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
public string SomeMethod()
{
return _someService.SomeMethod();
}
}
And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
thats all
PS also recommend to read this Introduction to Dependency Injection in ASP.NET Core

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.

C# ASP.NET Thread Safe static read only field

I have the following code in my ASP.NET project
public sealed class IoC
{
private static readonly IDependencyResolver resolver =
Service.Get("IDependencyResolver") as IDependencyResolver;
static IoC()
{
}
private IoC()
{
}
public static IDependencyResolver Container
{
get
{
return resolver;
}
}
}
public static class Service
{
public static object Get(string serviceName)
{
// Code to create and return instance...
}
}
Is IoC.Container going to be thread safe?
Initialization of static fields is thread-safe: that is, the .NET runtime guarantees that your field will be initialized only once in the program, no matter how many threads access it and in what order.
As Andrey points out, the Service.Get method itself needs to be thread-safe.
IoC itself looks ok, but the whole structure will not be thread-safe if resolver is not thread safe. If you want to have resolver per thread you can use attribute [ThreadStatic]

Resources