What I'm Doing Now
As it is now, every time I have a new project I need to work on (all of these projects use a pretty generalized base of functionality, but each have their custom functionality, quirks, etc.), I have to just copy the base project, and then modify the copied base project, to add the custom functionality.
The Idea
(I'm using ASP.NET MVC4, with Visual Studio 2012)
Basically, I'd like to have a "Base Project":
Base Project
-Controllers
-Models
-Views
Custom Project
-Controllers
-Models
-Views
that serves as the base for my MVC projects. Then, when I go to create a new project (spun off of the base project), I'd include the base project as a subproject to the solution, and in my new project, only have to write controllers/models/views that are different from the base (I'd like to just override those, or something similar).
This way, when I change the base project, the base projects of all of my different custom projects would be updated as well, this way I could update/bugfix/etc the base project, and not have to manually update each custom project to include this new base functionality.
The Problem
I understand that what I want is a little weird for MVC to handle, but I think I could get the whole routing engine to work the way I want, but I was just wondering if there were any solutions for this, that are a bit easier to implement. I feel like this is a fairly normal thing to want to do. Or am I thinking about the whole problem wrong?
What I've Tried
So far, I've created a base project, and a custom project, and I can get base functionality to appear in the custom project, if no Action is present in the custom controller, but the base project uses the custom project's View for that Action, whereas I need the base project to use it's own Action and View if they don't exist in the custom project.
Basically, if I go to:
http://mytest.com/Home/Index
And the base project has a HomeController, with an Index Action, but the custom project has neither of those, the routing engine will be unable to find a matching View for the base controller, because the views from the base project are not being copied to the output directory.
Conclusion
Basically I'm just looking for some general guidance. Am I looking at this the wrong way? Is it worth doing?
Also, if you find any misconceptions, please do correct me!
Thanks for your time.
This isn't weird for MVC at all. In fact, it's highly common. Just create a class library and put your models, controllers, helper classes, etc. in there. Then, you just add this class library as a reference in your other projects. The only complicated bit is sharing views, since Razor views are not compiled by default. However, for that, you can use Razor Generator.
Related
I am trying to create a good infrastructure for my web framework I am developing I have the following structure so far
solitude.admin web project to keep the controlers and views in how do I create this one I created a class libary but see you cannot have a web.config there
solitude.core will contain all my utililties and models
solitude.framework will be the core and meat of the cms platform my quesiton is how does one create a class libary project for asp.net mvc 4.6 to allow controllers and views to be shared i addded razor to a dll but i dont think that is correct approach
solitude.mvc this will contain the front end of the site i tried the below changing project guids to allow the sharing but its not working
I also changed the project type guids as suggested on aricltes on so but no joy I am trying to mimic our other platforms already work to futher my understanding.
<ProjectGuid>{152C761A-DD2E-4C1F-AF89-DFB2547A3BCA}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>solitude.admin</RootNamespace>
<AssemblyName>solitude.admin</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
Another point is if I was two have two sep projects admin and web how would one tell it to go to admin if user types www.domain.com/admin but yet be two independent web projects?.
I totally understand you. I'm in the same situation. I suggest you take a look at AREAS. I'm still learning it, but for what I've googled, it is the proper way to share views and controllers between projects.
This is one good link
I see good the separation of concerns. But have some questions:
1.- Why not making "solitude.admin" another web app project?
2.- Why aren't you using the expected naming conventions? That is a lot of lowercases you got there.
3.- Why would you like/need to share Controllers? Basically, there must be a
return View();
inside them.
For views, you could create some components based on parameters (which mostly, it comes to print out some HTML). You already have Shared Views but for the same project.
I am looking for a way to implement inheritance in specflow features. For e.g a base features class which has common scenarios which have to be tested.
3-4 derived features classes which inhert all the scenarios in the base class and add some of their own. Similarly the Binding class will also follow a inheritance structure. This is needed to test an ASP.NET MVC application which has a base controller (scenarios in base features class) and 4-5 implementations.
I can copy the features file for each derived controller class but this would lead to considerable duplication.
Is this possible in specflow, Or am I going down the wrong route? Please help. thanks,
I'm not 100% sure if this is the right path to take (read as, I've never needed to do anything like this). For me any inheritance and re-use comes in the Step Definitions (or Binding) classes. But even so...
I don't know if you can simply do this using the tools available in SpecFlow - but you have the following option so far as I can see (this isn't a tested theory... I might test it later - but I figured this might offer you an idea...)
The "code-behind" (designer-generate-code) for your Feature files are partial class implementations...
...so I guess you could create a "base" (generic) Feature file...
...then create a partial class file for each of your specific/implementation Feature files' code-behinds...
...each partial class will specify a base class which is the generated class name from the "base" Feature file code-behind.
Hopefully this helps a little.
EDIT:
Okay I've tested this theory... It would work as I've described above. I just created a new project with associated test/spec project, and did the above in the test/spec project. The test runner ran the base feature, and then ran the specific/implementation feature... which included the base feature again.
Have a go - it takes less than 5 minutes to knock up what I've suggested, and see if the result fits your requirement.
I've been struggling to do this in a way that fulfills all of my requirements.
Here is what we have in our library:
Base classes for controllers and services
Business objects (stores, departments, etc)
Common Partial Views (Login, Error, etc)
Base class for HttpApplication
General common code (read an INI file, create a db conn, etc)
The one requirement that has been giving me trouble is as follows:
Lives in one place on a server. (i.e. copy local = false)
This breaks because:
The DLL containing the HttpApplication class must be in the same directory as the web apps dll to launch. I haven't found a way around that. I'm ok with duplicating this code in every app, but would rather not.
The shared views don't like to work if I use Assembly.LoadFrom() to load the dll from the shared location. (I've been using this method to precompile my views)
Any namespace shortcuts in web.config break at runtime with compilation errors because the web.config is parsed before the assembly is loaded.
My question to you folks is how do you handle your common code in a similar environment?
The GAC seems to be more trouble than its worth, and we want all of our apps to be using the same code, and not have multiple apps on multiple versions and have to maintain all of that. Are there design patters/best practices that can guide us in this regard?
Also, as a bonus, if you can solve any of the problems above, that would be great, too.
Thanks!
Edit: I guess a question that follows is whether or not we should even have a directory with the common dll(s) on the server, or if they should only be deployed as projects are deployed/updated?
Firstly, you will want to separate out what you're trying to achieve. Don't create 1 library that does everything or you will have a Big Ball of Mud. Don't be afraid to create several maintainable libraries to achieve what you're after. Is there a specific reason it needs to be stored in one location?
For example, several of the items you mention are MVC or web specific. If you have items that can be reused by MVC, create a class library that contains MVC base classes you inherit and reference them in your project. Use the single responsibility principle as much as possible.
Regarding the other items you mentioned, like database connectivity, if it's reusable, abstract it out in a data access class library and reference it. Other simple operations like reading an ini file or creating a file, create another library and abstract it to easy to use methods.
I prefer to copy the library dlls locally. You never know when you will need to make changes to the library, but you don't want all of your projects to stop compiling. When you're ready to implement a new version of the library, copy the dll in and recompile.
Not sure why all the hate towards the gac. It was designed to handle this specific problem. Install your common dlls to the gac and all apps can see them. Need to deploy a new one, just re-install it in one place.
Keeping properties of multiple Visual Studio projects manually in sync is annoying. So, how can you share properties between multiple projects?
Edit: I refer to properties like conditional compilation symbols, treatment of warnings and errors etc., i.e., things you can configure in Project->Properties tabs or by editing the project XML file.
Similar questions have been asked before, see: 1, 2 and 3. However, in my understanding, the answers have been C++-specific. I am looking for an answer for C# projects. Nevertheless, do not hesitate to answer for other kinds of projects (Visual Basic etc.) if you keep the separation clear, because someone else than me might be interested.
This blog post proposes a solution to the problem, but I would prefer something simpler.
Also, you can at least solve a part of the problem in the following way (note that although I tested it, I did not test it thoroughly):
Create an AssemblyInfo.cs file with the assembly attributes you intend to share. Link to this existing item in the individual projects. Use the original (local) AssemblyInfo.cs and put project-specific assembly attributes there. Unfortunately, overriding attributes does not seem to work, and managing the attributes via the GUI is now limited.
For that kind of things, I prefer to have a separate Class Library Project, with one (or more) static classes storing the (static) properties. Then add a reference to that project from every project that needs to have those properties in sync, and all those projects will have the same values and you have to change it in only one place.
For example, let's say that I have the same app in web and desktop form. Things like connection strings and such will have to be the same for both. So I will create three projects:
MyProject.Web (Web application)
MyProject.Desktop (Windows forms application)
MyProject.Common (Class library)
Then I add a new static class in Common called Properties with a static property called ConnectionString that returns the connection string.
I then add a reference to Common in Web and Desktop, and when I want to access the connection string from any of them I use Common.Properties.ConnectionString.
We make very heavy use of the .vsprops files to have shared macros defined between our native projects.
Someone asking exactly the same question as you came up with the idea of adding a "blank" visual C++ project to the solution so that could import the vsprops file and the properties would be generally visible to the rest of the solution. If it doesn't sound too gross a hack, I can find out how it worked out.
I am designing a WPF application that uses a DLL with maybe 40 public classes. I need these to be public for a variety of reasons including ease of data binding and obfuscation. I would like to allow other people to use only a portion of these classes as an API for my software.
I thought I would create the main library (core.dll) and an API library (coreAPI.dll) with the API DLL to be referenced in a new project. Is there a way to allow coreAPI.dll to expose only a few of the classes that exist in core.dll? It's not so much a security issue as I primarily want to simply hide some of the unwanted classes from the Visual Studio Intellisense.
Again, internal classes for the ones I want to hide is not really an option because I need to data bind some of these classes in WPF and for that, they must be public. Are there any other ways of doing this?
As Damien already mentioned, if the only thing you'd like to do is to hide from Intellisense you can add the following attribute to your hidden classes:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
If the primary issue is Intellisense, then moving these classes into a separate namespace would surely do the trick?
Of course, you could split the classes into two separate assemblies. You may have some issues there with having to expose more classes than you want (because they now live in separate assemblies), which might be resolvable using the InternalsVisibleTo attribute