Hangfire Authorize runs multiple times - c#

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.

Related

Check Umbraco site is ready and it's connected to the database

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
}

Cannot find a dependent request in webtest

I have recorded a test with my webtest recorder in VS2015. When I am rerunning the test,at one point it fails at a dependent GET request of a .css file. The url in the webtest result shows something like this https://mycompany/blah/Style%20Guides/Global_CSS.css The error is a simple 404 error.
Now I go to the main request and search for this particular dependent request so that I can set its Parse_Dependent_Request option as False or set the Extected_Http_Status_Code as 404, which ever works is fine for me. But I am not able to find this particular dependent request under the main or any other request.
I have tried to change all the Parse_Dependent_Request option of all the dependent requests to false and understand which one actually sends the Get request, but none of them worked.I did a generate code from the webtest and literally did a page search but in vain.Do how do I get the request?
Many dependent requests (DRs) are not explicit in the web test. When parse dependent requests of the main request is true, Visual Studio processes the HTML response of that main request to find the DRs and they are added to the list of DRs. Any DR responses that are HTML may also be parsed and their DRs added to the list.
One technique to handle missing or problematic DRs is to run a plugin that modifies the list of DRs. The code below is based on the WebTestDependentFilter on page 189 of the "Visual Studio Performance Testing Quick Reference Guide" (Version 3.6) available from Codeplex. The Codeplex document has lots of other good information about web and load testing.
public class WebTestDependentFilter : WebTestPlugin
{
public string FilterDependentRequestsThatStartWith { get; set; }
public string FilterDependentRequestsThatEndWith { get; set; }
public override void PostRequest(object sender, PostRequestEventArgs e)
{
WebTestRequestCollection depsToRemove = new WebTestRequestCollection();
// Note, you can't modify the collection inside a foreach, hence the second collection
// requests to remove.
foreach (WebTestRequest r in e.Request.DependentRequests)
{
if (!string.IsNullOrEmpty(FilterDependentRequestsThatStartWith))
{
if (r.Url.StartsWith(FilterDependentRequestsThatStartWith))
{
depsToRemove.Add(r);
}
}
else if (!string.IsNullOrEmpty(FilterDependentRequestsThatEndWith))
{
if (r.Url.EndsWith(FilterDependentRequestsThatEndWith))
{
depsToRemove.Add(r);
}
}
}
foreach (WebTestRequest r in depsToRemove)
{
e.WebTest.AddCommentToResult(string.Format("Removing dependent: {0}", r.Url));
e.Request.DependentRequests.Remove(r);
}
}
}
The search criteria in the above code can easily be modified to (for example) check the middle parts of the URL.
Another variation is to set the expected response code of some DRs to other values. This might make a more accurate performance test than deleting the failing DRs as the server is still required to handle the request and return a response.

ASP.NET MVC5 - Override OnAuthorization() - 'MvcResources' is inaccessible due to its protection level

The main goal: I am creating a website (ASP.NET MVC 5) where I need to add some additional Authorization and redirection logic: For example, a user can only view page C after completing pages A and B. If they have completed page A and not B, and try to access page C, they will be redirected to page B.
After a good amount of research, my plan is to create a custom AuthorizationAttribute , and override OnAuthorization(). I want to do this responsibly, so I looked at the [source code][1] for this method, and want to only add logic to it, not take it away. I've started by copying that code over to my own subclass (which I include at the end of this post):
The problem is there are two elements here that I apparently cannot access:
MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache
CacheValidateHandler
The first is in System.Web.Mvc.Properties , and the error I get is that 'MvcResources is inaccessible due to its protection level'. All of the help I've seen online regarding this advises that the programmer change the access modifier for their class, but I can't since I didn't write this class: it's system code.
The second (CacheValidateHandler) 'does not exist in the current context'. It's a method in my parent class (AuthorizeAttribute), but it's private.
So is there something I'm missing? Does my subclass have to be in a special location (right now it's in a folder called Helpers) or do I have to do something different with namespaces? I'm still pretty new to C#. How can I safely override OnAuthorize if I'm not even able to repeat what the parent method does?
namespace MyApp.Helpers
{
public class MyAppAuth : AuthorizeAttribute
{
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
// If a child action cache block is active, we need to fail immediately, even if authorization
// would have succeeded. The reason is that there's no way to hook a callback to rerun
// authorization before the fragment is served from the cache, so we can't guarantee that this
// filter will be re-run on subsequent requests.
throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
}
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);
if (skipAuthorization)
{
return;
}
if (AuthorizeCore(filterContext.HttpContext))
{
// ** IMPORTANT **
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{
HandleUnauthorizedRequest(filterContext);
}
}
}
}
I believe I have a solution, but I would really love if someone with more experience could comment if what I'm doing is in any way unsafe.
For the first issue, I simply replaced MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache with a string, since this is one of the possible overloads of InvalidOperationException.
For the second issue, I copy-pasted the parent's private CacheValidateHandler() method:
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}

Disabling and enabling miniprofiler when working with Umbraco 7

This is a two part question, which circles around the same problematcis.
Without setting anything up in Global.Asax, and just inserting this line in my .cshtml file for my basic layout, and running my site in debug mode, the MiniProfiler is automatically displayed in my frontend.
#MiniProfiler.RenderIncludes()
Trying to shut down the MiniProfiler doesn't seem to work. I have tried something as obvious as the following code, but the MiniProfiler is still run, and is still represented in my frontend, when running my site locally:
protected void Application_BeginRequest()
{
MiniProfiler.Stop();
if (!Request.IsLocal)
{
MiniProfiler.Start();
}
}
Furthermore In Umbraco.Core's WebProfiler I found the following code:
if (GlobalSettings.DebugMode == false)
return false;
In my case, i would like to be able to let the Profiler run on my clients site, but that's not possible as DebugMode is always false when I publish my code to my clients site.
Ideally I would like to do something like:
protected void Application_BeginRequest()
{
MiniProfiler.Stop();
if (Request.IsLocal || Request.UserHostAddress == "My/developers IP")
{
MiniProfiler.Start();
}
}
How can I programmatically stop the MiniProfiler to set up cases where I don't want it to run when in DebugMode? And how can I make the MiniProfiler available for developers on my customers live sites?

How to track 500 errors on WebSockets (ws://)

I'm trying to play around with WebSockets on IIS 8.5. I started off with a couple of very basic C# classes from a lesson:
using Microsoft.Web.WebSockets;
using System.Web;
public class ChatHttpHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.IsWebSocketRequest)
context.AcceptWebSocketRequest(new WebSocketChatHandler());
}
public bool IsReusable
{
get { return true; }
}
}
public class WebSocketChatHandler : WebSocketHandler
{
private static WebSocketCollection clients = new WebSocketCollection();
private string name;
public override void OnOpen()
{
this.name = this.WebSocketContext.QueryString["username"];
clients.Add(this);
clients.Broadcast(string.Format("{0} joined.", name));
}
public override void OnMessage(string message)
{
clients.Broadcast(string.Format("{0}: {1}", name, message));
}
public override void OnClose()
{
clients.Remove(this);
clients.Broadcast(string.Format("{0} left.", name));
}
}
and a simple HTML client. The project builds ok, but when I try to connect to the handler, it returns error 500. The problem is that I cannot see what the exact error is, because neither Chrome nor FF load the response body for ws:// scheme, so i cannot even see it in the Network tab of Developer Tools (though IIS provides the body, as I can see from from the response' Content-Length).
Is there a way to see the response body in this situation? Or what am I missing with WebSockets in IIS?
The problem was with web.config.
I added
<httpRuntime targetFramework="4.5.1" />
to system.web section and it finally began to work
You should be able to see the cause of the error in the Windows Event Viewer.
Fiddler will show you the connection and that it has upgraded to web socket so you can use that tool to at least show you if the connection worked or not. I'm not aware of a tool which can show you the traffic flowing over the socket once it has been upgraded although there might be one.
Better still, debug it in Visual Studio with breakpoints and 'break on exception' set. You can tell VS to use IIS as the server by right clicking the web site and going to Property Pages then Start Options. Tick Use custom server and put your URL into the textbox. Click Specific page and choose your default page.
Comparing it to my working solution using the same DLL, I don't spot any obvious issues with the handling of the socket, so I would suggest commenting out this.name = this.WebSocketContext.QueryString["username"]; for now and replacing it with this.name = "TEST"; as that appears to be about the only code which deviates from the samples. Keep it simple until its working!

Categories