After many trials, I can't seem to get Nancy's Diagnostic Tracing to show anything beyond a set of empty white boxes. It appears one box per browser session. Yet the boxes never include any information.
Per the diagnostics page I've added a diagnostics password and set
StaticConfiguration.EnableRequestTracing = true;
I expected there to be at some sort of default tracing out of the box, but just in case I made a call to
this.Context.Trace.TraceLog.WriteLog(x => x.AppendLine("What's ip?"));
in one of my modules, and confirmed said module route was getting called. Still no indication there was tracing going on.
We're running NancyFx version 1.45 in a framework 4.7.1 app. Any suggestions on why this could be happening?
Thanks
Enable tracing and diagnostics by using a custom bootstrapper.
For NancyFx v1:
NancyOptions options = new NancyOptions
{
Bootstrapper = new CustomBootstrapper()
};
app.UseNancy(options);
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
StaticConfiguration.DisableErrorTraces = false;
StaticConfiguration.EnableRequestTracing = true;
if (!StaticConfiguration.EnableRequestTracing)
{
DiagnosticsHook.Disable(pipelines);
}
}
protected override DiagnosticsConfiguration DiagnosticsConfiguration => new DiagnosticsConfiguration() { Enabled = true, Password = #"A2\6mVtH/XRT\p,B" };
}
For NancyFx v2:
NancyOptions options = new NancyOptions
{
Bootstrapper = new CustomBootstrapper()
};
app.UseNancy(options);
public class CustomBootstrapper : DefaultNancyBootstrapper
{
public override void Configure(INancyEnvironment environment)
{
environment.Diagnostics(
enabled: true,
password: #"A2\6mVtH/XRT\p,B");
environment.Tracing(
enabled: true,
displayErrorTraces: true);
}
}
Related
I'm using the DotNetBrowser in my WPF emailing application to display the emails content. I'd like to block every remote content and remote images. I use this email privacy tester to check if I can correctly block the remote content.
I checked the documentation of the DotNetBrowser and I found that it's possible to disable couple of things using the BrowserPreferences setting. I disabled everything with the following piece of code:
BrowserPreferences pref = new BrowserPreferences {
ImagesEnabled = false,
JavaScriptEnabled = false,
PluginsEnabled = false,
WebAudioEnabled = false,
ApplicationCacheEnabled = false,
LocalStorageEnabled = false,
AllowDisplayingInsecureContent = false,
AllowRunningInsecureContent = false,
...
};
wpfBrowserView.Browser.Preferences = pref;
wpfBrowserView.Browser.LoadHTML(myHtml);
But this blocks just couple of the possible harmful contents. Then I set a custom LoadHandler, where I could prevent couple of more cases:
MyBrowserLoadHandler loadHandler = new MyBrowserLoadHandler();
loadHandler.Load += args => {
// just don't allow to load the content
};
wpfBrowserView.Browser.LoadHandler = loadHandler;
This is not enough, because it still fails two of them (the Link Prefetch and the CSS link tag).
I don't want to do a static analysis on the email's html to handle those cases as well, so I'm searching for an easier way to do it. For example in the Android's WebView, it's just two methods to call (setBlockNetworkLoads(true) and setBlockNetworkImage(true)) and it does the whole thing. Is there a solution like this in DotNetBrowser?
Finally I found the solution. I dropped out all of my tries what I posted above, and tried another way. The DotNetBrowser has a resource handler and you can set what kind of resources you'd like to allow to load and what not. Here is my code:
var network = wpfBrowserView.Browser.Context.NetworkService;
var resourceHandler = new MyResourceHandler();
resourceHandler.Load += args => {
ResourceType resource = args.Parameters.ResourceType;
switch (resource) {
case ResourceType.PREFETCH:
case ResourceType.IMAGE:
case ResourceType.MEDIA:
case ResourceType.OBJECT:
case ResourceType.STYLESHEET:
case ResourceType.FONT_RESOURCE:
case ResourceType.SUB_RESOURCE:
return false;
default:
// allow to load for the others
return true;
}
};
network.ResourceHandler = resourceHandler;
And the custom resource handler:
public class ResourceLoadEventArgs {
public ResourceParams Parameters { get; set; }
}
public delegate bool ResourceLoadHandler(ResourceLoadEventArgs args);
public class MyResourceHandler : ResourceHandler {
public event ResourceLoadHandler Load;
public bool CanLoadResource(ResourceParams parameters) {
return Load?.Invoke(new ResourceLoadEventArgs { Parameters = parameters }) ?? true;
}
}
So, adding this piece of code before loading the html into the browser view, it causes to pass every test in the email privacy tester. Then you can put a button for the user to load the remote content, and when the user clicks on it, you can allow every resource.
I have a Language entity with all supported languages in my db, each language has a culture string attribute. I want to load supported cultures from DB.
In my service initializer I have it:
public void ConfigureServices(IServiceCollection services)
{
// ... previous configuration not shown
services.Configure<RequestLocalizationOptions>(
opts =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-GB"),
new CultureInfo("en-US"),
new CultureInfo("en"),
new CultureInfo("fr-FR"),
new CultureInfo("fr"),
};
opts.DefaultRequestCulture = new RequestCulture("en-GB");
// Formatting numbers, dates, etc.
opts.SupportedCultures = supportedCultures;
// UI strings that we have localized.
opts.SupportedUICultures = supportedCultures;
});
}
How I can access my DB context inside it?
There is any other better way to do it?
I don't think there's an out of the box solution for this.
However, you can implement your own middleware that achieves this by using ASP.Net's RequestLocalizationMiddleware:
public class CustomRequestLocalizationMiddleware
{
private readonly RequestDelegate next;
private readonly ILoggerFactory loggerFactory;
public CustomRequestLocalizationMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
this.next = next;
this.loggerFactory = loggerFactory;
}
public async Task Invoke(HttpContext context /* You can inject services here, such as DbContext or IDbConnection*/)
{
// You can search your database for your supported and/or default languages here
// This query will execute for all requests, so consider using caching
var cultures = await Task.FromResult(new[] { "en" });
var defaultCulture = await Task.FromResult("en");
// You can configure the options here as you would do by calling services.Configure<RequestLocalizationOptions>()
var options = new RequestLocalizationOptions()
.AddSupportedCultures(cultures)
.AddSupportedUICultures(cultures)
.SetDefaultCulture(defaultCulture);
// Finally, we instantiate ASP.Net's default RequestLocalizationMiddleware and call it
var defaultImplementation = new RequestLocalizationMiddleware(next, Options.Create(options), loggerFactory);
await defaultImplementation.Invoke(context);
}
}
Then, we inject the required services and use the custom middleware in Startup.cs or Program.cs as follows:
services.AddLocalization()
/* ... */
app.UseMiddleware<CustomRequestLocalizationMiddleware>()
Do not call app.UseRequestLocalization(), because this would call ASP.Net's RequestLocalizationMiddleware again with the default options, and override the culture that has been resolved previously.
I have an Angular.js app that I am porting to .NET Core.
It was working fine in the previous version of .NET Core 3 preview; 3.2.
However, after upgrading to latest 3.3 some of the get requests are returning this error:
InvalidOperationException: Synchronous operations are disallowed. Call
WriteAsync or set AllowSynchronousIO to true instead.
I can't see why this is happening with only some requests and not others.
I believe that by default Angular.js does async: xhr.open(method, url, true);
Can anyone shed some light on this?
This problem is described here: https://github.com/aspnet/AspNetCore/issues/8302
The workaround for now is to manually set AllowSynchronous to true in startup.cs;
// Startup.ConfigureServices
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
It's worth noting that if you host on kestrel directly then your Program.cs should have appropriate ConfigureKestrel call
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.AllowSynchronousIO = true;
})
you can disable it for a special method
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
or disable in all application scope
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((context, options) =>
{
options.AllowSynchronousIO = true;
})
or in service configure startup
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
If you are using a CustomWebApplicationFactory like me, you can set the flag in its constructor, It makes my test direct from VS2019 works.
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup: class
{
public CustomWebApplicationFactory()
{
Server.AllowSynchronousIO = true;
}
I'm unable to get a custom cookie authentication handler working with IdentityServer4. I'm using ASP.NET Core Identity and have followed the official guide: https://identityserver4.readthedocs.io/en/release/topics/signin.html
I need to override the CookieAuthenticationEvents.ValidatePrincipal and CookieAuthenticationEvents.SignedIn event handlers.
I've written a class that inherits CookieAuthenticationEvents and overrides the two event handlers.
I'm assigning it to a custom cookie handler via:
var auth = services.AddAuthentication("MyCookies");
auth.AddCookie("MyCookies", options =>
{
options.Events = new RealtimeStatusCookieAuthEvents(Configuration);
});
Here's my code:
https://gist.github.com/Amethi/f3411038a9447d274c0b721698fc5e63
The event handlers don't fire, i.e. I'm expecting them to fire for each request (due to ValidatePrincipal) and when I come back to the site after closing the browser and sign-in using cookie authentication (SignedIn).
Anyone know what I'm doing wrong?
Update:
Even simplifying it as follows doesn't help. The event handlers don't fire.
var auth = services.AddAuthentication("CustomCookies").AddCookie("CustomCookies", options =>
{
options.Events = new CookieAuthenticationEvents
{
OnSignedIn = context =>
{
Console.WriteLine("{0} - {1}: {2}", DateTime.Now,
"OnSignedIn", context.Principal.Identity.Name);
return Task.CompletedTask;
},
OnValidatePrincipal = context =>
{
Console.WriteLine("{0} - {1}: {2}", DateTime.Now,
"OnValidatePrincipal", context.Principal.Identity.Name);
return Task.CompletedTask;
},
};
});
I managed to make my custom cookie authentication handler work by using the ConfigureApplicationCookie extension.
builder.Services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "IdentityServer.Cookie";
config.EventsType = typeof(CustomCookieAuthenticationHandler);
config.LoginPath = "/Account/Login";
});
And register the CustomCookieAuthenticationHandler handler
builder.Services.AddScoped<CustomCookieAuthenticationHandler>();
This is the handler implementation:
public class CustomCookieAuthenticationHandler: CookieAuthenticationEvents
{
private readonly IUserRepository _userRepository;
public CustomCookieAuthenticationEvents(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
// Your cookie authentication logic.
}
}
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-6.0
I'm using CefSharp (47) to render a webpage from a host that I have no control over, and I want to make some additional CSS tweaks to those provided by the host.
Reading up on various topics across GitHub (https://github.com/cefsharp/CefSharp/blob/cefsharp/47/CefSharp.Example/CefSharpSchemeHandlerFactory.cs), and here (CefSharp custom SchemeHandler), I wrote a custom scheme handler accordingly:
public class CustomSchemeHandlerFactory : ISchemeHandlerFactory
{
public const string SchemeName = "custom";
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
Console.WriteLine(request.Url);
if (schemeName.ToLower() == SchemeName.ToLower())
{
// Do some stuff
}
return null;
}
}
I attempt to bind it in my application in the following manner:
CefSettings settings = new CefSettings();
settings.CachePath = browserCachePath;
settings.RegisterScheme(new CefCustomScheme()
{
SchemeName = CustomSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new CustomSchemeHandlerFactory()
});
Cef.Initialize(settings);
The application then browses to the appropriate website, and uses the 'LoadingStateChanged' event to then fire off some JavaScript to inject the CSS file I want to load:
string linkText = "<link rel=\u0022stylesheet\u0022 type=\u0022text/css\u0022 href=\u0022custom://custom.css\u0022>";
var jsFunctionText = string.Format("(function() {{ $('head').append('{0}'); return true;}}) ();", linkText);
var injectionTask = await _myBrowser.GetMainFrame().EvaluateScriptAsync(jsFunctionText, null);
...which succeeds.
But my custom resource handler 'Create' event is never fired.
I can only presume that the handler isn't being registered properly, so I'd appreciate any advice/help in getting this working properly!
Thanks!