My Umbraco site has a recurring task which runs every 60 mins. The problem is when Umbraco is not installed yet, the task block the installation process.
I'm trying to detect the status of my Umbraco site by this:
var isApplicationInstalled = uQuery.RootNodeId != -1;
if (isApplicationInstalled)
{
// run the task
}
But uQuery.RootNodeId seems to always return -1 and the task has never run.
How to detect that Umbraco site is installed and it's connected to the database?
You can try this solution: Override ApplicationStarted method in ApplicationEventHandler.
The method is called when all required bootups is ready. Then you can override it, set a global setting to true (maybe you can define a global setting like UmbracoIsReady). And in your recurring task, you just need to retrieve UmbracoIsReady to check.
public class StartupHandler : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication,
ApplicationContext applicationContext)
{
base.ApplicationStarted(umbracoApplication, applicationContext);
//Set a global variable/information to make sure that the Umbraco is ready
Setting.UmbracoIsReady = true;
}
}
It's easier to check the Umbraco application's status via ApplicationContext:
ApplicationContext.Current.IsConfigured check Umbraco is configured.
ApplicationContext.Current.DatabaseContext.CanConnect check Umbraco can connect to the database.
So the code will be:
var isApplicationInstalled = ApplicationContext.Current.IsConfigured &&
ApplicationContext.Current.DatabaseContext.CanConnect;
if (isApplicationInstalled)
{
// run the task
}
Related
I followed the setup instructions here https://miniprofiler.com/dotnet/AspDotNetCore and got Mini Profiler working with my ASP.NET core web app. I pushed the code up to my staging site and now see the output on every request.
Previously local only access was documented here https://miniprofiler.com/
using StackExchange.Profiling;
...
protected void Application_BeginRequest()
{
if (Request.IsLocal)
{
MiniProfiler.Start();
}
}
How can I restrict miniprofiler to only show for local requests in ASP.NET core
From the documentation:
services.AddMiniProfiler(options =>
{
// (Optional) To control authorization, you can use the Func<HttpRequest, bool> options:
// (default is everyone can access profilers)
options.ResultsAuthorize = request => CanAccessMiniProfiler(request);
options.ResultsListAuthorize = request => CanAccessMiniProfiler(request);
}
You can implement it any way you like:
private bool CanAccessMiniProfiler(HttpRequest request)
{
// Add your logic here, e.g. check for local requests and certain roles
}
This code runs every seconds for me:
public class CustomAuthorizationFilter : IDashboardAuthorizationFilter {
public bool Authorize(DashboardContext context)
{
if (HttpContext.Current.User.IsInRole("Admin"))
{
return true;
}
return false;
}
}
Could you help me why? (I managed to null check HttpContext.Current.User, but this code runs every second)
When you have the dashboard open many Ajax request are made to keep the UI up to date. These are likely the request you are seeing. You can inspect the context in the debugger to see the specific route being called. Also the F12 developer tools in chrome (network tab) will give you some insight as well.
I am using the .NET framework 4.5
I have set the sessionState to expire after 60 minutes. Every pages that require to be "logged" inherits from a class named BasePage.cs. On the OnPreInit event, this class verify the Session object and redirect to the login page when the session is expired.
Here is the configuration of the sessionState (web.config) :
<sessionState timeout="60"/>
Here is my verification in the class "BasePage.cs" :
protected override void OnPreInit(EventArgs e)
{
if (HttpContext.Current.Session["infosession"] == null)
{
Response.Redirect("default.aspx");
}
}
This verification is working great when the user is navigating trough the pages.
In some pages, I am using a WCF Service (Ajax-enabled) called from javascript. Between the time the pages will be generated and the time the WCF Service will be called, the session may expire. Given that I should not assume that my Wcf Service's consumer will be a particular kind of software or have certain capabilities, as been a web browser, I can't do the verification there.
So after some explanations, here the question :
Is it possible, when the session expire (after 60 mins), to redirect automatically to the login page ?
Assuming you are looking for client side solution - just set timer to expiration time (i.e. 1 hour) and How can I refresh a page with jQuery?:
reloadTimer = setTimeout(60*60*1000, function() { location.reload();}
You may want to reset the timer if you get AJAX updates on the page that reset the session timeout.
Note that it no going to stop one from calling your WCF service directly, so it is not security measure but rather convenience.
why not do something like the following instead
public static string Infosession
{
get
{
object value = HttpContext.Current.Session["infosession"];
return value == null ? "" : (string)value;
}
set
{
HttpContext.Current.Session["infosession"] = value;
}
}
I would initialize the value in the OnSessionStart() in the Global.asax.cs file
HttpContext.Current.Session["infosession"] = string.Empty;
I would move this code
protected override void OnPreInit
to the Page_Load() event
another alternative
protected void Page_load(EventArgs e)
{
if (HttpContext.Current.Session["infosession"] == string.Empty)
{
Response.Redirect("default.aspx");
}
}
I am using NServicebus(version 4.6.3) with SQLTransport in my ASP.net web api project. I have different connectionstrings for the queues for different environments (Dev,QA,etc). My configuration looks like below:
public class BusConfigurator
{
public static IStartableBus Bus { get; private set; }
public static void DisposeBus()
{
if (Bus == null)
return;
Bus.Shutdown();
Bus.Dispose();
Bus = null;
}
public static void InitializeServiceBus(string connectionString)
{
var configure = Configure.With()
.DefineEndpointName("MyEndPoint")
.Log4Net(new DebugAppender { Threshold = Level.Warn })
.UseTransport<SqlServer>(connectionString)
.PurgeOnStartup(false)
.SetDefaultTransactionLevel()
.UnicastBus(); // Error is thrown here on second call
configure.MyCustomSQLServerPersistence();
Bus = configure.CreateBus();
}
public static void StartBus()
{
Bus.Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
}
}
I have a dropdown in the app so that the user can select the environment. Based on the selection, I want to reconfigure the bus. So, I call DisposeBus then pass the connection string to the IntializeServiceBus method followed by the startBus. It works first time but throws error below when it gets called again with different connectionstring:
Unable to set the value for key: NServiceBus.Transport.ConnectionString. The settings has been locked for modifications. Please move any configuration code earlier in the configuration pipeline
Source=NServiceBus.Core
Line=0
BareMessage=Unable to set the value for key: NServiceBus.Transport.ConnectionString. The settings has been locked for modifications. Please move any configuration code earlier in the configuration pipeline
Is NServicebus intended to be used/configured this way? (I am guessing probably not) If not then is there a workaround/different approach for this?
In V4 or below, there is no way to do it by normal human means. There is only one Bus per AppDomain. All of the configuration API is static, so if you try, you get exactly the problems you ran into.
By "human means", I mean that it might be possible to do something crazy with spinning up a new AppDomain within your process, setting up a Bus within that, and then tearing it down when you're finished. It might be possible. I haven't tried it. I wouldn't recommend it.
In V5, the configuration API is completely redesigned, is not static, and so this is possible:
var cfg = new BusConfiguration();
// Set up all the settings with the new V5 Configuration API
using (var justOneBus = NServiceBus.Bus.Create(cfg).Start())
{
// Use justOneBus, then it gets disposed when done.
}
That's right. It's disposable. Then you can do it again. In your case you wouldn't want to put it in a using block - you would want to set it up somewhere, and when the dropdown gets switched, call Dispose on the current instance and rebuild it with the new parameters.
Keep in mind, however, that the Bus is still pretty expensive to create. It's definitely still something you want to treat as an application-wide singleton (or singleton-like) instance. You definitely wouldn't want to spin up a separate one per web request.
I have tried PhluffyFotos example on Azure SDK 1.2 and it works perfect. Today I have installed on another (clen) computer Azure SDK 1.3 and I have also want to try PhluffyFotos on it but it does not work. I have problem with this part:
if (!Roles.GetAllRoles().Contains("Administrator"))
{
Roles.CreateRole("Administrator");
}
It seems it somehow does not load the custom RoleProvider (TableStorageRoleProvider). Do you have any idea what it could be?
I get the following error: "The Role Manager feature has not been enabled.", because of the following exception "'System.Web.Security.Roles.ApplicationName' threw an exception of type 'System.Configuration.Provider.ProviderException'".
Can someone test this example and see what is the problem? http://phluffyfotos.codeplex.com/
Firsty I have the "SetConfigurationSettingPublisher" problem with this example, but I have successfully resole it.
EDIT:
I have look deeper into it and I am sure there are a problem with Role provider. Somehow the Roles class do not read config file. Have anyone any idea why?
I have the exact same problem with my own project. I verified with Fusion logs that the assembly which contains the custom providers dont even load. so it seems the problem is somehow related to the web.config settings being ignored.
To run PhluffyFotos example on Azure SKD 1.3 you have to the following:
Change reference Microsoft.WindowsAzure.StorageClient from 1.0 to 1.1
Move "GetConfigurationSettingValue" to the Global.asax "Application_Start" event.
Move Role related initialization to the Global.asax "Application_BeginRequest" event, but you have to ensure that it executes only once. Example:
private static object gate = new object();
private static bool initialized = false;
protected void Application_BeginRequest()
{
if (initialized)
{
return;
}
lock (gate)
{
if (!initialized)
{
// We need to check if this is the first launch of the app and pre-create
// the admin role and the first user to be admin (still needs to register).
if (!Roles.GetAllRoles().Contains("Administrator"))
{
Roles.CreateRole("Administrator");
}
if (!Roles.GetUsersInRole("Administrator").Any())
{
Roles.AddUserToRole(RoleEnvironment.GetConfigurationSettingValue("DefaultAdminRoleUser"), "Administrator");
}
initialized = true;
}
}
}
I posted a version of the code with the fixes suggested by Peter to rapidshare here:
http://rapidshare.com/files/434649379/PhluffyFotos.zip
For those who don't want to fuss around fixing the dependencies etc.
Cheers,
Daniel