You must call the "WebSecurity.InitializeDatabaseConnection" but I DO - c#

*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.*
I am getting this error, on and off, randomly and not sure what the reason is. In my route config. Index controller, index action is the default one. and here is the definition:
[Authorize(Roles = "admin")]
[InitializeSimpleMembership]
public class IndexController : Controller
Everytime I restart the application, if i didnt log out, i get the above error. Then I log out and log in again and error disappears.
Why is that happening?
How can i resolve this?
I am using localdb if that would help.

The problem occurs because the Application_Start() function only triggers on the first user action. But the IndexController is triggered before the user can event perform an action. Just remove the [InitializeSimpleMembership] from your project, It also gave me a lot of frustration...
Just add the following code to your global.asax
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
public class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
using (var context = new UsersContext())
context.UserProfiles.Find(1);
if (!WebSecurity.Initialized)
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
Of course make sure you create the correct dbContext() and have the correct InitializeDatabaseConnections properties set that match your project.
Kr

Related

Custom Controller, not working with areas

I have a custom controller in my project because I use Structure Map as an IOC Container. When I add Datatables.mvc (library for jquery grid), and call a view from areas, the custom Controller does not work at runtime and gives me an error. When I remove the Datatables.mvc from references, the project compiles successfully and renders the view form controller as well.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
setDbInitializer();
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver = SmObjectFactory.Container.GetInstance<Microsoft.AspNet.SignalR.IDependencyResolver>();
}
private static void setDbInitializer()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<OnlineAcademyDbContext, Configuration>());
SmObjectFactory.Container.GetInstance<IUnitOfWork>().ForceDatabaseInitialize();
}
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, $"Resource not found : {requestContext.HttpContext.Request.Path}");
}
return SmObjectFactory.Container.GetInstance(controllerType) as Controller;
}
}
protected void Application_EndRequest(object sender, EventArgs e)
{
HttpContextLifecycle.DisposeAndClearAll();
}
}
and this is the error when i called a view from areas and Datatable.mvc has been add to references:
System.Web.HttpException: Resource not found : url of area...
ControllerType is null
thanks all.
well. problem has been solved. the solution is change the computer. i think the iis or Os got confuse cause

Stop Async call in Global.aspx

i have two mvc applications in one solution.
now i need to maintain session when user redirects from one application to another.
so what my logic is,
passed GUID in URL.
get GUID in another projects Global.asax file using Init() method.
Log in another user.
i done whole code, added below.
now, i am getting call in Init() method but it also calls other methods which are passed in URl.
i.e. call becomes asynch, so because of that, user redirected to other page.
do i need to change my logic or just code?
below is my Global.asax file code.
public override void Init()
{
var userId = Guid.Parse(Request["UserGUID"].ToString());
if (userId != null && userId == Guid.Parse("1B541D9A-AC3E-466F-897B-6F9033F4533C"))
//my logic of login management
}
After more then 8 hours of R&D, i found solution that really helped me.
Actually my way is proper but the method is not right.
Application_AcquireRequestState
is the proper method for my scenario.
my code is :
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
public void Application_AcquireRequestState(object sender, EventArgs e)
{
var userId = HttpContext.Current.Request["UserGUID"];
if (userId != null)
{
Session["UserGuid"] = Guid.Parse(userId.ToString());
//My logic for session handling..
}
}
}

Response Redirect Using In MVC

I want to create connection between global.asax and my controller. We are using a database in our website. We have a code to check whether the database exists or not. If it doesn't not exist, we want to display a message like "database initializing" etc..
Database check in GLOBAL.ASAX :
public class MvcApplication : System.Web.HttpApplication
{
public static bool flag;
protected void Application_Start()
{
Database.SetInitializer<PhoneDexContext>(null);
var connString = ConfigurationManager.ConnectionStrings["DatabaseConnection"].ConnectionString;
using (PhoneDexContext db = new PhoneDexContext())
{
if (!db.Database.Exists())
{
flag = true;
db.Database.CreateIfNotExists();
}
}
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
protected void Application_BeginRequest()
{
if (flag)
{
Response.Redirect("Loading/LoadingScreen");
}
}
}
But we have a problem with using response redirect. It returns
{"Response is not available in this context."}.
We have a controller which is LoadingController and it has this code;
public class LoadingController : Controller
{
// GET: Loading
public ActionResult LoadingScreen()
{
return View();
}
}
But we can't jump to this part. How can i make connection?? Thanks
First, Application_Start does not handle any user requests. It is just perform some start up initialization. It invoked only once when app starts. To do some checks based on user's actions and properly respond you need to move these checks into Application_BeginRequest method.
Second, you also need to check if user already requesting /Loading/LoadScreen before responding with redirect to that page. Otherwise you will get an infinite redirects until database created.
public class MvcApplication : HttpApplication
{
private static bool dbInitialized;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// We can do it asynchronously to not block other initialization code.
Task.Run((Action)CreateDataBase);
}
private static void CreateDataBase()
{
Database.SetInitializer<PhoneDexContext>(null);
using (PhoneDexContext db = new PhoneDexContext())
{
if (!db.Database.Exists())
db.Database.CreateIfNotExists();
}
dbInitialized = true;
}
protected void Application_BeginRequest()
{
if (!dbInitialized && !this.Request.Url.LocalPath.StartsWith("/Loading/LoadingScreen", StringComparison.OrdinalIgnoreCase))
{
this.Response.Redirect("/Loading/LoadingScreen");
}
}
}
You can to further and move checks into the ActionFilter as you will able to work with RouteData and check action and controller parameters instead of url. Combined with nameof that would be less error-prone to route changes, renaming, refactoring and so on.
I think this answer will give you what you want: Return different views in a controller
In your case instead of the response.redirect use return View("/Loading/LoadScreen"); ...or something simular
try this
HttpContext.Current.Response.Redirect("/Loading/LoadScreen");
beacuse Response object is not avaliable in application_start method of global.asax.
you must use HttpContext.Current for any situation.
You can also use the 'Auto-Start feature' (How to warm up an ASP.NET MVC application on IIS 7.5? : Darins answer). This will execute once, before the website is ready to serve requests. The downside is you can't show the user a 'please wait' window. Personally I would not check at every request if the database is existent or not. Just execute it; the database update should not take very long I guess?
Application_Start happens before ASP.Net starts processing the request.
You could set a global static flag to indicate the error condition, then handle Application_BeginRequest and check the flag and redirect.
static bool _isDbLoaded;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start(){
Database.SetInitializer<PhoneDexContext>(null);
var connString = ConfigurationManager.ConnectionStrings["DatabaseConnection"].ConnectionString;
using (PhoneDexContext db = new PhoneDexContext())
{
if (!db.Database.Exists())
{
_isDbLoaded = false;
db.Database.CreateIfNotExists();
}
}
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
protected void Application_BeginRequest(){
if(!_isDbLoaded){
Response.Redirect("Loading/LoadingPage");
}
}
Since Request and Response won't be available in your Application_Start event, You might consider having this code somewhere in the MVC request-response pipeline. An action filter is a good place.
public class VerifySetupIsGood : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var dbSetDate = context.HttpContext.Application["DbSetDate"] as string;
if (String.IsNullOrEmpty(dbSetDate))
{
//to do : Execute your custom code to check db existence here
var values = new Dictionary<string, string> { { "action", "LoadScreen" },
{ "controller", "Loading" } };
var r = new RouteValueDictionary(values);
//redirect the request to MissingDatabase action method.
context.Result = new RedirectToRouteResult(r);
}
base.OnActionExecuting(context);
}
}
Here we are first checking whether the application variable has a valid entry for "DbSetDate" key. By default, it will not be there. Then you have to execute your custom code to check whether your db exist. If not, Redirect to the LoadScreen action.
Register this filter globally so that it will be executed for any request coming to your application.
GlobalFilters.Filters.Add(new VerifySetupIsGood());
Now in when you are done with setting up your database, update this application variable to have a valid value.
HttpContext.Application["DbSetDate"] = DateTime.Now.ToString();
Remember, Application variable states will also gets reset. So don't just rely on that. You should run your custom code to check your db exists inside the if condition. If condition is to prevent your custom db check for every single request.

MVC global exceptions

I am coding an MVC 5 internet application, and I have a question in regards to handling exceptions globally.
I have my Application_Error setup in my global.asax file. This caters to errors such as 404 HttpExceptions.
How can I send all errors that occur in a controller to the Application_Error function? An example is the following exception:
System.Web.HttpRequestValidationException: A potentially dangerous
Request.Form value was detected from the client (name="").
I have written a OnException(ExceptionContext filterContext) for my controller, but am not sure on how to get the Application_Error function to handle these errors. Do I need to pass the exception from the OnException function, or is this the wrong approach?
Thanks in advance.
You can create a global filter by adding the following class to your App_Start folder:-
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
HandleErrorAttribute can be replaced with your own custom Exception Filter.
All you then need to do is make sure you add the following line of code to the App_Start method of your Gloabal.asax :-
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//AreaRegistration.RegisterAllAreas();
//RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}
}
Hope this helps.
I'm using some kind of http-module which gives me exactly what you are asking for:
public class MyModule : IHttpModule {
public void Init(HttpApplication context) {
context.Error += OnRequestError;
}
private void OnRequestError(object sender, EventArgs e) {
var context = ((HttpApplication)sender).Context;
var error = context.Error;
if (error == null)
return;
var errorType = error.GetType();
if (errorType == typeof(HttpException))
// do something
// this is what you are looking for
if (errorType = typeof(HttpRequestValidationException))
// do something, whatever you want
// works for me, so should work to you too
}
}
To get the module to work, you can use web.config or DynamicModuleHelper:
Install Microsoft.Web.Infrastructure and WebActivatorEx via nuget
Add a Bootstrapper class to your project
Register module at PreApplicationStartMethod
Sample:
// File: Bootstrapper.cs (contains class Bootstrapper)
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using WebActivatorEx;
using WhatEver.It.Is;
[assembly: PreApplicationStartMethod(typeof(Bootstrapper), "Bootstrap")]
namespace WhatEver.It.Is {
public class Bootstrapper {
public static void Bootstrap() {
// Do what do you need just before the application get started
// like registering modules, etc...
DynamicModuleUtility.RegisterModule(typeof(MyModule));
}
}
}

Simple Injector unable to inject dependencies in Web API controllers

I am attempting to do some basic constructor DI with Simple Injector, and it seems that it is unable to resolve the dependencies for Web API controllers.
I have an API controller in an "API" folder, that is outside the "Controllers" folder.
I have also tried placing it within the "Controllers" folder, but
that did not seem to make much of a difference. The stack trace that
I receive is similar to the one presented in this question.
I am using a fresh install of the "Simple Injector MVC Integration Quick Start" NuGet Package (v. 2.1.0).
I have the base SimpleInjectorWebApiDependencyResolver from the documentation, which is also the same as found here.
I am using Entity Framework, and have looked at the discussion
thread about changes to correctly load the context.
This does not
seem to be a problem, but I still receive the following error:
Type 'MyProject.API.ArticleController' does not have a default
constructor
System.ArgumentException at
System.Linq.Expressions.Expression.New(Type type) at
System.Web.Http.Internal.TypeActivator.Create[TBase](Type
instanceType) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func`1& activator) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)
It would be appreciated if someone could offer me some suggestions, on whether anything should be modified from its current state/call order.
ArticleController (basic structure):
public class ArticleController : ApiController
{
private readonly IArticleRepository articleRepository;
private readonly IUserRepository userRepository;
private readonly IReleaseRepository releaseRepository;
public ArticleController(IArticleRepository articleRepository, IUserRepository userRepository, IReleaseRepository releaseRepository)
{
this.articleRepository = articleRepository;
this.userRepository = userRepository;
this.releaseRepository = releaseRepository;
}
// GET api/Article
public IEnumerable<Article> GetArticles(){ // code }
// GET api/Article/5
public Article GetArticle(int id){ // code }
// PUT api/Article/5
public HttpResponseMessage PutArticle(int id, Article article){ // code }
// POST api/Article
public HttpResponseMessage PostArticle(ArticleModel article){ // code }
// DELETE api/Article/5
public HttpResponseMessage DeleteArticle(int id){ // code }
}
SimpleInjectorInitializer:
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcAttributeFilterProvider();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IArticleRepository, ArticleRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<IReleaseRepository, ReleaseRepository>();
}
}
Global.asax.cs:
public class WebApiApplication : System.Web.HttpApplication
{
private void ConfigureApi()
{
// Create the container as usual.
var container = new Container();
// Verify the container configuration
// container.Verify();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ConfigureApi();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
TLTR: the problem is caused by the implicit way Web API handles resolving controller types; register your Web API controllers explicitly and you'll see where the problem is.
Here is a step by step what is happening under the covers:
The System.Web.Http.DefaultHttpControllerActivator calls into the SimpleInjectorWebApiDependencyResolver and requests the creation of an API controller.
SimpleInjectorWebApiDependencyResolver forwards that call to the SimpleInjector.Container instance.
That Container instance however, does not have any explicit registrations for that API Controller (since you supplied an empty container to the resolver).
Since there is no explicit registration, the container tries to do a last minute registration for that type.
That Controller type however depends on interfaces that can't be resolved because they are not registered in the container (remember, your container is empty).
Although the container would normally throw an exception, null is returned in this case, because the type is requested through the IServiceProvider.GetService method and the type was not registered explictly.
The SimpleInjectorWebApiDependencyResolver's GetService method will return null as well, since it's by definition that it should return null; It should return null when no registration exists (which currently is the case).
Since the DependencyResolver returned null, DefaultHttpControllerActivator will fall back to its default behavior, which means creating that type itself, but this requires the controller to have a default constructor.
Long story short, the problem is caused by the implicit way Web API handles resolving controller types.
So the solution here is to:
Have only one single Container in your web application. This prevents all sorts of trouble and complication of your configuration.
Register all Web API Controllers explicitly in the container. Registering controllers explicitly will ensure that Simple Injector will throw an exception when a controller can't be resolved. Besides, this allows you to call container.Verify() which will make the application fail during startup when the configuration is invalid (a verifiable configuration is important). And this also allows you to diagnose the configuration which gives you even more confidence about the correctness of your configuration.
My advice is to place MVC and Web API in their own project. This will make things much easier.
Registering all Web API controllers can be done with the following code:
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
UPDATE:
Because this error is so common, newer versions of the SimpleInjectorWebApiDependencyResolver class will simply never return null when a controller type is requested. Instead it will throw a descriptive error. Because of this you should never see error anymore, as long as you use the official SimpleInjectorWebApiDependencyResolver.
Following setups work for me:
1) include Unity.WebAPI from https://www.nuget.org/packages/Unity.WebAPI/
2) in UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// **** Important note -----
// register all your components with the container here
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
3) in Global.asax file
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Getting started with Unity.WebAPI
To get started, just add a call to UnityConfig.RegisterComponents() in the Application_Start method of Global.asax.cs
and the Web API framework will then use the Unity.WebAPI DependencyResolver to resolve your components.
e.g.
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents(); // <----- Add this line
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Add your Unity registrations in the RegisterComponents method of the UnityConfig class. All components that implement IDisposable should be
registered with the HierarchicalLifetimeManager to ensure that they are properly disposed at the end of the request.

Categories