I have a big .net mvc 2 project where we are using MvcContrib Portable Area. There is a main web site which load many modules (PA modules).
The main application contains Site.Mater into its ~\Views\Shared folder. each module also has own Site.Master which inherit from that main one.
At the moment we are using something like:
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" MasterPageFile="~/Views/Shared/Site.Master" %>
After compilation the view handle the main Site.Master right as it is a relative path.
Now I've received a requirement to build views during the compilation. So I've enabled MvcBuildViews = true in each web PA module project.
Of course, I'm getting errors saying "/temp/Views/Shared/Site.Master is not found".
How to keep Portable Area with content embedded and ensure that views do not contain errors?
Any idea?
You can't.
I'm dealing with this same issue and you can't fake the physical location of a file easily.
The only solution is to make a placeholder and removing the non-embedded placeholder file as part of the build process. The benefit of this technique is the non-embedded resource will load a bit faster in development.
Another thing to consider is that loading your views as embedded resources is pretty slow. Having your build process move the centralized "common" views up to the local project will result in better performance for your users.
in case you just want to make sure that everything works fine you could use Watin and write some unit tests that are going to check this
Related
How can I go about separating my MVC project into UI specific (JS, CSS, Images, Fonts, and maybe Views) and Controller/Model specific (Controllers, Helpers, Models, and may be Views). Since our front-end developers work mostly independent of Visual Studio, I was looking for best practices in separating projects. Any pointers or sample projects?
This is how we finally ended up doing it.
Create a separate visual studio project called SolutionName.Client (this is where all frontend js and scss files go)
Create you MVC project called SolutionName.MVC (this is the asp.net mvc project)
Using Grunt.JS write tasks that compiles all js and css files and drops them to SoltuionName.MVC/Content folder
Similarly write tasks that drops all Views (razor files) into SolutionName.MVC/Views folder.
In Project build settings, add a pre-build tasks to run grunt task.
This setup took few hours to get it working but it is now quite useful.
You can easily do this and I've done it for each of my projects in MVC as well.
One project has your Controllers, ViewModels, and in my case, any custom logic related to Dependency Resolution for MVC and custom classes related to security authentication with MVC. Basically any code that touches the MVC framework core and is not involved in rendering content.
The other one has pretty much everything that you use on the client-side, and code needed for the front end. Which in my case, code-wise, is very minimalist and included some code for Glimpse and Elmah. The rest is your Views, Styles, Scripts, static content like downloads, etc.
As for the files in App_Start, My views project has Bundles, Filters, and obviously any HtmlHelpers you may have, custom css transformationslike for LESS.
My Controller's App_Start has the RouteConfig. These aren't necessarily critical it's just the way I ended up organizing mine and really depends what aspects you need access to during the startup of those components.
I will say that to save yourself time, in your Views/web.config file, add a namespace entry for your Company.Project.ViewModels namespace so that it's done in one place and you don't have to add it to each view, as this namespace would reside in your Controllers Project.
Your project with the Views will be your startup project. Just make sure in the global.asax your calls to the FilterConfig, RouteConfig and BundleConfig all resolve correctly.
It's fairly easy to do, my recommendation is to try it yourself and split it out the way you want and if you have problems come back and ask about the difficulties rather than looking for a step by step guide.
Bottom line is, yes it's possible and yes it works,
I'm looking at this MVC WebApi starter kit (for Angular/TypeScript)
Ignoring all the client side code, I noticed the author has made a WebApi that is extremely bare bones. Has has taken out most scaffolding including _ViewStart.cshtml, _Layout.cshtml, and forgoed the convention of controllers in Controllers folder and views in View folder under subdirectory with same name of controller, etc.
He added some interesting Routing and Validation classes that I havent seen before in a Core folder and put controllers in Api folder and Views directly into Views folder with an Index.cshtml at the root.
It's very clean and barebone project structure for a standalone web api that will do nothing except serve data to a client heavy application. I kind of like it this way but before jumping ship I'm wondering what drawbacks this approach has and if I'm actually giving up any core features of the framework by doing it this way. For example, clearly MVC Areas are being given up here in favor of flexibility to create your own view folders structure and seperation of application sections (I'm okay with getting rid of MVC Areas I rarely used them anyways). Another thing is I don't think a Controller action method can return View() and it will find it in the Views folder by convention of the controller name. I'm also okay with that since I will only be serving JSON data and will use 100% client side templating.
Are there any other core features that are being abandoned that I'm missing that may make me regret going with this project structure?
When I create Web APIs that are hosted in IIS, the only files in my web application are web.config, global.asax and global.asax.cs. Everything else is not required.
Take a look at this template if you haven't already before you decide how to structure your ASP.Net MVC / Angular project:
http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83
You can always add components into your project later, so I wouldn't seat it too much. I like to start with a lean/mostly empty project first and add things myself so that I fully understand what I'm adding.
I'm currently evaluating Durandal for use in an enterprise ASP.NET MVC application.
However the default conventions used by Durandal seem to conflict with the MVC conventions I've grown accustomed to.
The HotTowel MVC template by John Papa is great, but this too seems to "do away" with MVC conventions in favour of Durandals by putting things in an App folder.
A couple of the issues I have with these conventions are:
Views are potentially split across two locations (/App/views and /Views).
Scripts are also split across two locations (/App/durandal and /Scripts).
Views are not in the default MVC locations for the RazorViewEngine.
I would prefer to keep each element contained in the appropriate MVC conventions e.g.
/Controllers/
---- HomeController
---- AdminController
/Scripts/
---- durandal/
---- viewmodels/
-------- Home
-------- Admin
/Views/
---- Home
---- Admin
My questions are:
Is it possible to configure Durandal to achieve the above (or something similar)?
Is it wise to venture away from the default Durandal conventions?
What are the potential issues in doing so?
1. Is it possible to configure Durandal to achieve the above (or something similar)?
Yes, you can have any folder structure your heart desires. Durandal does not impose any folder structure on your application but it does have a default convention which is completely overridable.
If you are using Durandals router then you will want to look into how to configure it to find modules. There are many ways of doing this, I prefer to create my own convention by overriding the router.autoConvertRouteToModuleId.
If you are not using the router plugin then you will have to manage the uris for your modules yourself and this is done by following requirejs' convention and using this convention along w/ durandals composition module.
Also, you can override how it finds the views to bind to your modules by overriding the viewlocators convention. Durandal provides an very simplistic way of structuring small applications right out of the box but if you need to build larger applications then it is recommended you create your own conventions.
2. Is it wise to venture away from the default Durandal conventions? 3. What are the potential issues in doing so?
So, there are the conventions of how to discover modules and how to discover views which are completely overridable. And I recommend you do override these and choose a way that suites you best. But, as for placing durandal inside your scripts folder as you have listed above I dont think its a good idea.
The reason I dont recommend this is because I see the scripts folder as a place for all your third party scripts that are NON-AMD modules. This is because Durandal also comes with an optimizer.exe which makes minifying/compressing/uglifying all your html/css/js (amd) files into 1 file.
If you keep your entire application under an app folder and then have the durandal folder inside your app folder the optimizer just works because it lives inside the app/durandal/amd folder. So, when you execute it, it will transverse up 2 directories to your app folder and then scan every subfolder to create a app.build.js requirejs optimization file.. and then it will compress your entire application to one file for you.
This beats having to hand edit an app.build.js file everytime you add a new file to your project. Sure.. there are other tools out there which can do this too.. but you will have to spend time learning their api and how to configure them. If you dont feel like devoting the time to learning something like grunt then this optimizer is kick ass. Personally, I like the ability to just double click something and have my whole application built for me.
As for placing all your third party libraries which are non-amd in a seperate scripts folder I would look into compressing those seperately like using MVC's bundling. The reason I would bundle those seperately is because you know those files arnt changing very often and if you bundle those into a seperate js file they can be cached by the browser seperately. Whereas if your spa is changing, which it it probably will.. then you want the browser to cache that seperately so it only has to re-download your compressed application.
What we do (this is what I have seen Rob doing too:) is that to create folders inside the /App folder depending on the functional areas of the app. Then just create view and view model file inside these folders.
Trick is to have a "viewUrl" property in each view model to tell durandal which view to use.
This way of structuring the application is useful for large projects where there are many views/view models ; avoids confusion when your project grows.
define(['durandal/app', 'durandal/system', 'plugins/router'],
function (app, system, router) {
var vm = {
viewUrl: 'myfolder/myview.html',
};
return vm;
}
);
You can still use viewLocator.useConvention(); when you bootstrap your application; durandal will still find the view as long as you have viewUrl property.
ok, i know there are a lot of posts online that specify how to do iterations with MVC.
my question is slightly different. when i used to do iterations using WebForms, i was creating one thing only and finishing that one thing till the end which was including the deployment on production.
for example, i was creating a webpage and deploying it, then i create the second page and deploy it. so .dll files were added to my bin folder while the previous dlls remain untouched. at the other hand, when i was making a change latter on, there was this one file that needed to be replaced on production.
now here is the question, how can i acheive the same thing in mvc? beause it just doesn't deploy each page into an individual dll. each time that i add something i have to redeploy the application dll which is not really wise! i played around with deployment options in visual studio but no luck!
There is nothing preventing you from putting controllers and other code in separate assemblies and dropping them in an existing application. Like any ASP.NET based application an MVC application will automatically restart if you add or modify any file in the bin folder or modify web.config.
If you're using Razor you can use RazorGenerator to generate code for your views and compile them into the same assembly.
You may need to write some additional logic though to get routes, model binders etc. wired up correctly.
For a more structures approach to compose the application of separate modules, you may want to look into portable areas. This is an extension to ASP.NET MVC that allows you to package the entire module (including views, css, js etc.) into a single assembly.
First thing, you have to work on the title of the post, it does not match the content of the post.
In asp.net mvc u can choose to deploy only what changed. I.e. If you only changed the .cshtml file, then you can just replace it with the file in production. However if you change any controller class (C#/Vb code), then you will have to upload the web project dll file too so that this new changes are available in the production env
I'm looking for a way to reference a shared external _layout.cshtml from MVC 3 and Razor.
A little back story:
We have multiple developers. All of them are working on separate MVC applications that all need the same look and feel. All these applications will be deployed to the same site for example
http://www.example.com/App1/
and
http://www.example.com/App2/
The look and feel will be generated by the CMS and dropped into a different folder
http://www.example.com/Layout/_layoutExt.cshtml
I've tried
MasterName = #"C:\inetpub\wwwroot\layout\_LayoutExt.cshtml";
But it gives me the error that it can't find the file
The view 'Index' or its master was not
found or no view engine supports the
searched locations. The following
locations were searched.
My eventual solution was to use Symbolic links (or junctions or hard links) to link the needed file into the view folder. This way the CMS writes to one location and my app reads from another. Not the clean solution I was looking for.
You'll probably need to make your own view engine that support reading file outside the web application home directory.