Cassette.Nancy unbundled files returning 404 - nancy

I've added Cassette.Nancy to an existing Nancy web project. This works fine when I set CassetteNancyStartup.OptimizeOutput = true; but when this is set to false I get 404 on the unbundled resources.
Here's my set up.
I'm using the following packages:
Cassette.Nancy version="2.1.1"
Cassette version="2.4.1"
Nancy version="0.22.2"
Nancy.Owin version="0.22.2"
Nancy.Viewengines.Razor version="0.22.2"
The files are like so:
Content
file1.css
file2.css
Scripts
script1.js
script2.js
CassetteBundleConfiguration:
public class CassetteBundleConfiguration : IConfiguration<BundleCollection>
{
public void Configure(BundleCollection bundles)
{
bundles.AddPerSubDirectory<StylesheetBundle>("Content");
bundles.Add<ScriptBundle>("Scripts");
}
}
in my _Layout.cshtml:
#{
Bundles.Reference("Content");
Bundles.Reference("Scripts");
}
#Bundles.RenderStylesheets()
#Bundles.RenderScripts()
And finally in Bootstrapper:
public Bootstrapper()
{
CassetteNancyStartup.OptimizeOutput = false;
}
Like I say this works fine when CassetteNancyStartup.OptimizeOutput is set to true but when false each of the resources return a 404 like this one:
GET http://localhost:10005/_cassette/asset/Content/file1.css?cf7a7edf515a8184a0c53ec498c583cc64bb0e63 404 (Not Found)
Any suggestions?

This issue was down to me not adding the Owin handler in the web.config. Adding this fixed it.
<system.webServer>
<handlers>
<add name="Owin" verb="*" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb" />
</handlers>
</system.webServer>

Related

Is there a way to avoid X-Frame-Options in a CEF Windows Chromium Desktop App?

I created a simple app using the suggested "app init", then I dropped a pre-compiled ReactApp in place.
The app has a browser within it that uses an IFrame to host the navigated pages, but in some pages, it issues the following error:
Refused to display 'https://www.theverge.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.", source: http://localhost:5000/#/
https://content-security-policy.com/
The page above has a series of ways to how this could be avoided, and Chromium has a flag that could help, where it disables security and as many suggested in other posts and questions, that may help with this issue.
Beyond those, there is the possibility of writing a reverse-proxy that could potentially take care of this.
Either way what I need to know is if there is a way to achieve that through parameters within the "app" tool, something like:
app --unsecure
app publish --unsecure
app publish-exe --unsecure
Thank you
I've tried a number of different options inclusing using a Custom .NET Core Desktop Apps that adds the disable-web-security switch which used to work:
static int Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseUrls("http://localhost:5000/")
.Build();
host.StartAsync();
var config = new CefConfig(Debug)
{
Args = args,
StartUrl = startUrl,
HideConsoleWindow = false,
OnBeforeCommandLineProcessing = (processType, commandLine) => {
commandLine.AppendSwitch("disable-web-security");
}
};
return CefPlatformWindows.Start(config);
}
But no longer does so appears this security restriction is now embedded inside of Blink.
Using a Proxy to Remove Headers
The only solution I could get to work is to use a proxy that calls the internal .NET Core server which proxies the downstream URL but ignoring the X-Frame-Options header.
This is easy to do using ServiceStack's Proxy Feature where you can register a proxy to https://www.theverge.com that strips the X-Frame-Options header with:
Plugins.Add(new ProxyFeature(
matchingRequests: req => req.PathInfo.StartsWith("/theverge"),
resolveUrl: req => $"https://www.theverge.com" + req.RawUrl.Replace("/theverge", "/")) {
IgnoreResponseHeaders = {
"X-Frame-Options"
}
});
This will let you embed The Verge in your App with:
<iframe src="/theverge" style="width:100%; height:800px;" frameborder="0"></iframe>
Which will render TheVerge in an iframe as expected:
Working Demo
You can find a working example of this in ServiceStack.CefGlue.Win64.AspNetCore:
Startup.cs
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseServiceStack(new AppHost());
app.Run(context =>
{
context.Response.Redirect("/metadata");
return Task.FromResult(0);
});
}
}
public class AppHost : AppHostBase
{
public AppHost() : base("MyApp", typeof(MyServices).Assembly) { }
public override void Configure(Container container)
{
Plugins.Add(new SharpPagesFeature());
Plugins.Add(new ProxyFeature(
matchingRequests: req => req.PathInfo.StartsWith("/theverge"),
resolveUrl: req => "https://www.theverge.com" +
req.RawUrl.Replace("/theverge", "/")) {
IgnoreResponseHeaders = {
"X-Frame-Options"
}
});
}
}
[Route("/hello")]
public class Hello : IReturn<HelloResponse>
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
public class MyServices : Service
{
public object Any(Hello request) =>
new HelloResponse { Result = $"Hello, {request.Name}!" };
}
ServiceStack.CefGlue.Win64.AspNetCore.csproj
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.*" />
<PackageReference Include="ServiceStack.CefGlue.Win64" Version="5.*" />
<PackageReference Include="ServiceStack" Version="5.*" />
<PackageReference Include="ServiceStack.CefGlue" Version="5.*" />
<PackageReference Include="ServiceStack.CefGlue.Win64" Version="5.*" />
<PackageReference Include="WinApi" Version="4.0.0" />
You'll also need to copy CEF binaries from the ServiceStack.CefGlue.Win64 NuGet package with:
<ItemGroup>
<Content Include="locales\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="swiftshader\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="*.pak">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="*.lib">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="*.dat">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="*.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="*.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="*.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
<Copy SourceFiles="%(Content.Identity)"
DestinationFiles="$(OutputPath)\%(Content.Link)"
SkipUnchangedFiles="true"
OverwriteReadOnlyFiles="true" />
</Target>
index.html
<!DOCTYPE html>
<html lang="en">
<body>
<h1>X-Frame-Options Proxy Test</h1>
<iframe src="/theverge" style="width:100%; height:800px;" frameborder="0"></iframe>
</body>
</html>

How to get DNN to create a sitemap links for custom modules?

We have a DNN website with custom modules which uses Ajax to load Grid Items.
How can I get DNN to create a sitemap for these links as well? I am currently using an external program but would like DNN to generate these sitemaps automatically with all our links.
The site is: https://www.parrot.co.za
You would typically do this by creating a SiteMap provider for your module.
You can find a working example in my DNNSimpleArticle module on GitHub
public class Sitemap : SitemapProvider
{
public override List<SitemapUrl> GetUrls(int portalId, PortalSettings ps, string version)
{
var listOfUrls = new List<SitemapUrl>();
foreach (Article ai in ArticleController.GetAllArticles(portalId))
{
var pageUrl = new SitemapUrl
{
Url =
ArticleController.GetArticleLink(ai.TabID, ai.ArticleId),
Priority = (float)0.5,
LastModified = ai.LastModifiedOnDate,
ChangeFrequency = SitemapChangeFrequency.Daily
};
listOfUrls.Add(pageUrl);
}
return listOfUrls;
}
}
and then you need to register the sitemap with DNN in the .DNN file used during the module's installation
<component type="Config">
<config>
<configFile>web.config</configFile>
<install>
<configuration>
<nodes>
<node path="/configuration/dotnetnuke/sitemap/providers" action="update" key="name" collision="overwrite">
<add name="DNNSimpleArticleSiteMapProvider" type="Christoc.Modules.dnnsimplearticle.Providers.Sitemap.Sitemap, DNNSimpleArticle" providerPath="~\DesktopModules\dnnsimplearticle\Providers\Sitemap\" />
</node>
</nodes>
</configuration>
</install>
<uninstall>
<configuration>
<nodes />
</configuration>
</uninstall>
</config>
</component>

How can I use a service or global function in the #Component declaration?

I have a service that helps with some routing issues related to my environment and now I need to cope with template routing issues
Ideally I would be able to do something like this:
import { PathSvc } from './globals/path.svc';
#Component({
templateUrl: this.pathSvc.alias + '/app/my.comp.html'
})
export class MyComp {
constructor(private pathSvc: PathSvc) { }
}
Of course that doesn't work because the service isn't made to be used in the component declaration so I get a runtime console error:
requests:38 Error: TypeError: Cannot read property 'pathSvc' of
undefined(…)
Typescript and modular JS in genaral is a new thing to me. Maybe there's a more direct way to import my function to a bunch of modules and use it anywhere I want?
I realize this isn't an optimal approach and I should be getting these results using the
<base href="/{alias}" />
methodology but that's not happening right now.
The short of it is that somehow all that stopped working while I tried to make my ASP.Net MVC + Angular 2 app more dynamically aware of its hosting environment and handle back end and front end routing conflicts. I'd like to get this working in more of a "right way" but at the moment, I just need it to work so my boss is happy and a global routing script seems like the way.
if i correctly understood, you want to create a service that can act as an helper out of the angular's DI process.
Like #Günter_Zöchbauer said, an Injectable can't be used outward of an instance of an Ng2 object (Component, Injectable...) but in your case, create an injectable is irrelevant. Create an angular app doesn't mean that all your files must contain angular objects, you can also create basic classes/constants..
For example, if you want an helper that build an url for you, you can create a class and use it in a component declaration simply by importing it.
//urlbuilder.ts
const host:string = 'http://foo.bar.com';
export class UrlBuilder {
static generate(file:string = '') {
return host + file;
}
}
// component.ts
import {UrlBuilder} from './urlbuilder';
#Component({
templateUrl: UrlBuilder.generate('/foo.html')
})
export class FooComponent {}
You can even export a function instead of the class, it will work too.
The following code show the same code as above but with a function and an es6 tag.
//urlbuilder.ts
const host:string = 'http://foo.bar.com';
export const UrlBuilder = urlBuilderFn;
//basic tag function that build a template string with potential variables
function urlBuilderFn(strs, ...raws) {
let builtStr = '', length = strs.length;
for(let i = 0; i < length; i++)
builtStr = strs[i] + (raws[i] !== undefined && raws[i] !== null ? raws[i] : '');
return host + builtStr;
}
// component.ts
import {UrlBuilder as url} from './urlbuilder';
#Component({
templateUrl: url`/foo.html`
})
export class FooComponent {}
However, if wanna use your helper with the DI too (for whatever reasons, need for angular deps..) you can make an injectable class with a static method.
//urlbuilder.ts
const host:string = 'http://foo.bar.com';
#Injectable()
export class UrlBuilder {
constructor(private http:Http) {}
static generate(file:string = '') {
return host + file;
}
doSomething() {
return this.http.get(UrlBuilder.generate('/foo/bar'))
}
}
// component.ts
import {UrlBuilder} from './urlbuilder';
#Component({
templateUrl: UrlBuilder.generate('/foo.html')
})
export class FooComponent {
constructor(private builder:UrlBuilder) {}
ngOnInit() {
this.builder.doSomething()
}
}
On the other hand, if your only issues are with the templates why don't you write them directly as template string or just import them with your task manager (webpack..). Generally, if you don't have dynamic view and so, have to generete them from your server, prefer to avoid http calls to retrieve them and load them directly in the javascript files.
I've dealt with this issue and I solved it by making the baseHref a setting inside my configuration/appSettings. Make the Angular page container an .ASPX page, on page loads, set the baseHref from the configuration. Here is the snippets from my Web.config:
<appSettings>
<add key="AppBaseUrl" value="/MyAngularApp/" />
</appSettings>
And here are the re-write rules to make your Angular app function properly while being hosted in IIS:
<rewrite>
<rules>
<rule name="Rewrite Index to Root" stopProcessing="true" enabled="true">
<match url=".*" />
<conditions>
<add input="{URL}" pattern="^(.*)(/index.aspx)$" />
</conditions>
<action type="Redirect" url="{C:1}" />
</rule>
<rule name="Angular" stopProcessing="true" enabled="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.aspx/{R:0}" appendQueryString="true" />
</rule>
</rules>
</rewrite>

Google Cloud Endpoints JS Client will not Load - Getting 404 with broken URL

This is probably going to need more information than I provide, but since I have no idea what is going on, I'll start with what I know.
I am using GAE with Google Cloud Endpoints.
My API loads and works great when accessing it from the API explorer, but it will NOT work when I load it in the web app.
function startApp(user) {
var appName = 'pwLandlordApp',
app = packageApp(appName);
configureApp(app, user);
angular.bootstrap(document, [appName]);
}
function verifyAuthenticated() {
gapi.client.oauth2.userinfo.get().execute(function (resp) {
var authenticated = !resp.code,
user;
if (authenticated) {
user = resp;
startApp(user);
} else {
$('#manualAuthenticationLink').show();
}
});
}
function authenticate(immediateMode) {
var callback = verifyAuthenticated,
clientId = {
development: '227265048827-17u88it981ie38hopqr8nl7tnep0d8l2.apps.googleusercontent.com',
production: '227265048827-5f98s99qoigh8f0tmp106uplek8g7mq5.apps.googleusercontent.com'
};
gapi.auth.authorize({
client_id: clientId.development,
scope: ['https://www.googleapis.com/auth/userinfo.email'],
immediate: immediateMode
}, callback);
}
function authenticateAutomatically() {
var immediateMode = true;
authenticate(immediateMode);
}
function authenticateManually() {
var immediateMode = false;
authenticate(immediateMode);
}
function loadResources() {
var appRootUrl = {
development: 'http://localhost:8080/_ah/api',
production: 'https://property-management-suite.appspot.com/_ah/api'
},
numberOfResourcesToLoad = 2,
verifyAllResourcesLoaded;
verifyAllResourcesLoaded = function () {
numberOfResourcesToLoad -= 1;
if (numberOfResourcesToLoad === 0) {
authenticateAutomatically();
}
};
// If loading additional resources change numberOfResourcesToLoad appropriately.
gapi.client.load('propertyWrasslerApi', 'v1', verifyAllResourcesLoaded, appRootUrl.development);
gapi.client.load('oauth2', 'v2', verifyAllResourcesLoaded);
}
function init() {
loadResources();
}
Keep getting the following error.
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:8080/_ah/api/_ah/api/discovery/v1/apis/propertyWrasslerApi/v1/rpc?fields=methods%2F*%2Fid&pp=0
Tried checking out an earlier commit that I know worked and the problem persisted, WTF! So not sure what is going on.
Help, please! Been at this for hours.
UPDATE:
My web.xml file. I know It's empty but that has always worked for me as I only have an API.
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.5"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
</web-app>
UPDATE 2:
appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>property-management-suite</application>
<version>1</version>
<threadsafe>true</threadsafe>
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
The problem seems to be related to the javascript client library. Are you loading it directly from https://apis.google.com?
Update: This is a bug. Google is looking into it:
https://code.google.com/p/google-api-javascript-client/issues/detail?id=147
I'm having the same problem with an app in python. It looks like a problem in the Google Javascript Library (apis.google.com/js/client.js). I'm currently looking for an older version of the client.

nancy razor first time setup - route not found 404

Steps I took to setup project:
created new asp.net project
Install-Package Nancy.Viewengines.Razor
added Views/hello.cshtml (simple hello world html)
added MainModule.cs
hit ctrl-F5 (it returns the directory listing)
change url to localhost:41915/hello
Then I get 404 resource not found.
What am I missing?
// MainModule.cs
namespace MyProj
{
using Nancy.Routing;
using Nancy;
public class MainModule : NancyModule
{
public MainModule(IRouteCacheProvider routeCacheProvider)
{
Get["/hello"] = parameters => {
return View["hello.cshtml"];
};
}
}
}
You need the Nancy.Hosting.AspNet package too.

Resources