Is there a super duper happy path for sharing views and site content across Nancy projects?
For example, I'd like to run the same site via self hosted / IIS.
The easiest way to do that is to put all of the actual application code into a class library - that is your modules, views, js, css, bootstrapper and whatever supporting code you have. You then setup a view location convention in your Bootstrapper such the view can be found in both a web server and self hosted context. This could be the ResourceViewLocationProvider:
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override NancyInternalConfiguration InternalConfiguration
{
get
{
return NancyInternalConfiguration.WithOverrides(
x => x.ViewLocationProvider = typeof (ResourceViewLocationProvider));
}
}
}
Alongside that you can have a web projects, with e.g. nancy.hosting.owin setup up and a project reference to the class library with the application code. Similarly you can have a console application with just nancy.hosting.self setup and a reference to the class library.
I describe this setup in more detail on my blog and in my Nancy book.
Related
I am quite new to NancyFX and investigating its capabilities. Once thing I am trying to figure out is whether it's possible to compose a large site using multiple modules (classes derived from NancyModule) in a way that makes it possible to build routes from several module definitions.
For example, I have the following module, AbcModule:
public class AbcModule : NancyModule
{
public AbcModule() : base("/api/systems/abc")
{
Get["/"] = _ => "ABC API Host";
Get["/domains/"] = _ => Response.AsJson(Domains.All);
Get["/domains/{name}"] = x => Response.AsJson(Domains.All.Single(y => x.Name == y.Name));
}
}
What I don't want is to expose "api/systems/abc". I want this path to be defined in another module (i.e. RootModule) that defines "api/systems" and build a list of available systems at runtime. Then AbcModule is unaware of its container defines all its routes relative to some URL.
Is this possible in NancyFX?
UPDATE. Let me give you an example (and I am open to admit that I've misunderstood something, in this case please hint me where is the flaw). There is a Web service that is going to expose a potentially large collection of services or plugins. Each plugin is responsible for its own resource types and resource structure, but why should it know how its container's routing rules? Imagine that a developer is working with the plugin "music" wrapped in a Nancy MusicModule which defines routes "/rock", "/metal" and "disco". But on a production machine his code is deployed in a Web site where MusicModule becomes a part of a "Hobby" service that defines "music", "sports" and "films" routes. Finally, there is a root module that defines "api" route.
So here is the question: can MusicModule only deals with the routes that belong to its domain, with the rest of the full path be added by other modules, so on a development machine with only MusicModule available "rock" resource can be accessed directly at localhost:xxx/rock, and on a production machine it's exposed from other (chained) modules, so the access path is machinename:xxx/api/hobby/music/rock?
And if this is a bad idea, please elaborate why. What can be wrong with hiding from a module the full route path?
what you are asking for is running at a different root url, where /api/systems/ is not part of your application, but your hosting environment. Nancy does not understand the concept of global root path. It can be done quite easily by intercepting the incoming requests (using a Before hook on the application level) and re-writing the URL of the incoming URL.
I created an empty Web API project and have this:
GlobalConfiguration.Configure(WebApiConfig.Register);
When I create a non-empty Web API project I have this
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
RouteConfig.RegisterRoutes(RouteTable.Routes);
I do not need MVC Areas.
I do not need MVC filters.
I do not need Bundling/Minification as this will be handled my client side libraries.
I DO NEED (at first sight) the RouteConfig because I need the MVC HomeController which renders the initial _Layout_cshtml HTML file.
I am doing a Single Page App (AngularJS) + Web API.
Because of the last point above I have to add MVC stuff to my Web API Project.
Is there any possibility (angularJS/other JS libraries) on client side when the browser starts to initially retrieve a html file and render this instead of calling the MVC RenderBody() Method?
For a SPA with WebApi, you should not let MVC or .NET do anything to the static side of the site. That will just slow everything down and it's completely unnecessary. The words ".Net controller" and SPA should not be used together :)
The setup I use, when I want to test end-to-end with WebApi, is to have a static site in IIS, say mydomain that contains the entire contents of your static site, at least index.html. Then I create a subfolder under that site called "api" that is a full application. This will be your WebApi. Since it's a subfolder under mydomain CORS is no problem, but as far as IIS is concerned the root is pure static, and the "api" folder is a full-blown .Net application.
Here's what it looks like in IIS...
You could just embed the HTML file as a project resource and return it directly?
public class HomeController : ApiController
{
[HttpGet]
[Route("/")]
public HttpResponseMessage Get()
{
var content = new StreamContent(this.GetType().Assembly.GetManifestResourceStream(this.GetType(),"home.html"));
content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
return new HttpResponseMessage() { Content = content };
}
}
Really all you need to do is setup a static HTML file wherever you keep your other static resources (scripts, css, etc).
You can then just redirect to it from your root controller:
public class HomeController : ApiController
{
[HttpGet]
[Route("/")]
public RedirectResult Get()
{
return Redirect("/contents/myapp.html");
}
}
I have a solution with this structure :
ProjectName.Domain ==> contains POCO classes (EntityFramework
code first classes) ProjectName.DataAccess ==> contains DbContext
and EntityFramework mapping codes. ProjectName.Task ==> It's my
bushiness layer . ProjectName.Presnetation.MvcClient ==> It's
ASP.NET MVC web client.
ProjectName.Presentation.SilverlightClient ==> It's Silverlight 5
client. ProjectName.WCFRiaClassLibrary ==> It's layer between
business logic and Silverlight client
I've decided to handle logic such as queries and CRUD operations in business logic and use ProjectName.Task in domain service class.
I can't find any sample that use EF code first approach and load entities from another project , can you please help or give me link ? because when I try to create my DomainService class without wizard I can't find generated proxy classes in silverlight client project .
I'm doing something like this :
[EnableClientAccess()]
public class CrudService : DomainService
{
private readonly IEntityTask _entityTask;
public CrudService(IEntityTask entityTask)
{
_entityTask = entityTask;
}
public IQueryable<Entity> GetAll ()
{
return _entityTask.GetAll().AsQueryable();
}
}
Is this possible to use code first classes from another project with WCF Ria Service ?
What is wrong with my approach?
Defintely possible. Take a look at this question to see possible problems with wcf ria + ef
EDIT:
I've just written a small blog post attaching to it a functional project. You can find it here
I am building an Asp Net website in Visual Studio that uses Razor developed HTML pages. I would like to be able to use some C# from the javascript on one of the web pages (this is not creating a plugin that would be displayed in the browser.) I have tried to create a simple Cs class that has a single method that returns a fixed string to test this. The following code is in the ManagedCsClass.cs file is in the App_Code folder in my project.
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ManagedCsClass
{
public ManagedCsClass()
{
//
// TODO: Add constructor logic here
//
}
public string ReturnText()
{
return "Text from ManagedCsClass";
}
}
What I am not clear on is where to create the object that would be used by the HTML page (in the same .cs file as the class, another .cs file, or from a call from the HTML browser page).
And what code do I need to use in the javascript to reference the object/method?
Thanks for any help or guidance you can provide.
Mark
You are trying to use "ActiveX" com objects, this requires the dll containing that class registered on the client and you will have a lot of security/deploy issues ( the client must trust your object and have the framework installed ). It is not the best way to create a web app today.
I have the following Ria Service define:
namespace SilverlightTest.Web
{
[EnableClientAccess()]
public class ContactService : LinqToEntitiesDomainService<AdventureWorksEntities>
{
public IQueryable<Contact> GetContactSearch(string lastName)
{
ContactRepository rep = new ContactRepository();
return rep.SearchByLastName(lastName);
}
}
}
When I compile the solution, my SilverlightTest project does create the SilverlightTest.Web.g.cs file and the appropriate Context objects are created when I look at it. However, when I attempt to import the SilverlightTest.Web namespace to access the Data Context class for the above service, it says it cannot find the Web namespace.
The only difference I can see between what I'm doing and many examples that are out there on the web is that my AdventureWorksEntities data context is located in a separate business object dll. I tried to query the context directly instead of using the Repository Pattern I'm attempting to do and it also isn't work working.
Any ideas? Is it possible to have Ria Services access a separate DLL handling data access or does it HAVE to be in the same project?
I've been able to put the Ria service in a separate project before, although I do remember having issues. Not sure exactly what it was, but I would check two things: your references and your web.config (in the hosting website). When you add a ria service to a web project it does some things behind the scenes that wire everything up correctly.
Could try adding a service to your web project temporarily and see what it adds.
It seems that Resharper does not recognize the .gs files and their name spaces. If you disable R# or just code without intelisense it works.