How to create a package for Umbraco with Visual Studio? - c#

How do I create a package for Umbraco inside Visual Studio? I know that you can create a package inside Umbracos backoffice, but I am not interested in that right now. I just need something simple, like a hello world package

Unfortunately, it's not so simple. It depends what is going to be the package content. If those will be static files, dlls etc. - it's a job for MsBuild and you can use it to gather all the required files and create a package or even distrubute it.
There's a great article by Jeavon Leopold on 24days.in: http://24days.in/umbraco/2014/packaging-with-appveyor/ combined with CI done with AppVeyor.
The challange starts when you want to include document types, datatypes or any other Umbraco-related content there too. And this is really easy to be done with Umbraco Packaging through the backoffice (you just need to select what should be included). Using your custom build and automatic packaging, you need to remember that if anything should be included inside the Umbraco backoffice, it needs to be handled by the creation of those objects in your code (e.g. on application startup events custom handlers) and ensure that if it's not exist it should be re-created etc.
Personally, I suggest you to check how other package creators are handling it, as a lot of packages is open-sourced e.g:
Pipeline CRM (adding custom datatables for future usage in custom section(s)): https://github.com/theotron/PipelineCRM/blob/master/GrowCreate.PipelineCRM/RegisterEvents.cs
Nested Content (custom property editor registration): https://github.com/umco/umbraco-nested-content/blob/develop/src/Our.Umbraco.NestedContent/PropertyEditors/NestedContentPropertyEditor.cs
Personalisation Groups (doument types, nuget packaging etc.): https://github.com/AndyButland/UmbracoPersonalisationGroups
etc.

Related

develop shared library alongside another project without having them be in the same solution

Let's say I have a c# project Foo and a classlibrary called Bar
I'm wanting to develop Bar alongside Foo which will use Bar as a shared library. I'd like to keep these Foo and Bar in their own git repositories.
When I debug Foo, I'd like to be able to step into Bar to see what it's doing under the hood. When I make changes to Bar, I'd like to be able to have my changes reflected in Foo. It's okay if I'd have to build Bar first for my changes to take effect.
When I eventually deploy Foo, I'd like to import Bar as a nuget package, rather than including it as a part of the solution for Foo
Is this possible in c#? I've been trying to develop a shared library and a repository that uses that library as a template for future projects. I've tried to publish Bar as a nuget package to my local filesystem but it's been giving me problems; I'm unable to step into functions that call into Bar from project Foo and when I make changes to Bar I have to build, pack, then publish the library again. If I don't bump the version number of bar when I do this, this results in errors where I have to go to the nuget package in my filesystem and delete it manually.
Aside
If you're interested Bar contains extension methods for setting up a connection to a message broker along with classes for configuration definition and "contract" classes that need to be shared among projects.
This is a common problem when developing code in nuget dependency chains.
One solution is to use something like NuGetReferenceSwitcher.
The disadvantage is that the tool will change your csproj files back and forth and you need to take good care of not commiting unwanted changes.
Another solution I employ successfully is to create a sibling project to your Foo project that uses ProjectReference to Bar instead of PackageReference.
I detailed the approach on my blog.
It involves editing your project files by hand, which is simple in SDK-style projects.
If you are comfortable with (or want to learn) that, here is the Gist:
Extract everything except the PackageReference to Bar from the Foo project into a Foo.props file.
Import that Foo.props file into the Foo project. Note that until now, effectively nothing has changed.
Create a copy of the Foo.csproj in some other folder and name it e. g. FooDev.csproj. Link the source files from the Foo (sic!) project into the FooDev project (using the technique that ΩmegaMan already described in their answer). Include FooDev.csproj in your Foo solution.
In your FooDev.cproj change the PackageReference to Bar to a ProjectReference.
You now have both a Foo.csproj that uses a PackageReference to Bar and a FooDev.csproj that uses a ProjectReference to Bar.
You will be able to immediately see the effects of the changes you make to Bar on the FooDev project.
you can go red path or blue.
"Is this possible in c#?" - This is not c# or any language. This is solution/project management. Many things are possible. You can definitely develop as raw projects or DLL. Include debug-built DLL and PDB file into your nuget, and you will be able to step through your referenced library.
You don't have to use a separate solution from yout GIT/TFS. You can develop using any local solution, not binded to source control.
I'm wanting to develop Bar alongside Foo which will use Bar as a shared library. I'd like to keep these Foo and Bar in their own git repositories.
Yes. In Foo, add all files from Bar as needed by add as Link. Namespaces and files will be honored as if they existed in Foo; but no files will be copied...only referenced.
This is an old Silverlight trick to share one set of code between two projects because of the two different versions of the CLR from the web services to the Silverlight project. It allowed models to be brought over from the web services without trying to pull in a dll which had a totally different CLR.
Create the code in project 1. Then for project 2, add the files by linking them from project 1. To do that type of add, its really adding a symbolic link to the file(s).
How
The trick is to include as a link into the project as needed.
In the second project right click and select Add then Existing Item... or shift alt A.
Browse to the location of the file(s) found in the first project and select the file(s).
Once the file(s) have been selected, then on the Add button select the drop down arrow.
Select Add as link to add the common files(s) as a link into the project.
I'm unable to step into functions that call into Bar from project Foo and when I make changes to Bar I have to build, pack, then publish the library again.
The linking of files, as mentioned, will gain access to the file as if the file was actually within the project, but the file physically resides elsewhere. If the linked file(s) change, those changes are reflected in the project that linked them in. Building due to changes still applies, but that should be minor.
I can't try this out right now, but I believe this is what we used to do (several jobs ago).
Create a project/solution for Bar, deploying it to a local NuGet package source. Add it to its own Git repo.
Create a project/solution for Foo, dependent on Bar via Nuget. Put it in a separate repo.
Create a FooPlusBar solution in the same folder (and repo) as Foo.sln. Start with an empty solution. Then add the Foo project and them the Bar project. If you are careful to keep changes to Bar updated in the NuGet package, I'm pretty sure you can get the debugger to recognize the Bar sources when you are debugging Foo from within the FooPlusBar solution. Yes, a single project can be part of more than one solution
Again, I think should mostly just work (no guarantees, though). I don't remember if you need to update the version number of the Bar package every time you make a change

How to deploy "extension method" within a VSIX extension?

Due to the wording (many meanings of "extension" and "method"), I am utterly unable to find any information about my question on the interwebs. So I am asking here:
Is it possible to deploy "extension methods" with a VSIX extension?
Clarification:
By "extension method" I mean something like
public static string SomextExtension(this string s, string p) {
retrun s + p;
}
By VSIX extension I refer to a custom extension, that gets installed via a
SomeCoolExtension.vsix
The goal is:
A user installs the VSIX, gets a few features (mainly custom code generators in my case) and additionally has access to "Hello".SomeExtension(" World"); within their source code.
I am slowly thinking this just isn't possible as I have tried everything I could come up with and as stated in the beginning, it is virtually impossible to search for it on googls.
If it really is impossible, I would at least love to understand why.
So a simple "no" might be a valid answer, but if you could elaborate, that would put my coding soul to rest :-)
Specs: I am using VS2017 and the new "Visual Studio AsyncPackage", but if you know an answer for older version, I sould be happy to try them.
You can use both approaches:
An extension (.vsix) provides the greatest flexibility, because it can provide commands (buttons on menus, context menus and toolbars) that, on demand by the user, can 1) Insert code in the active document 2) Add files with code or other assets 3) Add references to Dlls that the extension can deploy in the source folder of the project, etc. Also, it can do all that not only on demand, but automatically watching events and examining if some conditions are met, for example, a solution is created, or it is loaded, a project is added, it already contains a code file or not, it already has a reference or not, etc. Needless to say, all this flexibility comes from some complexity.
A NuGet package can add DLLs to the references or code files to a project, it can execute a PowerShell script when the NuGet package is added to a project that can modify the project, it can modify the build process adding new MSBuild targets/tasks (being the Microsoft.VSSDK.BuildTools NuGet package to create a VSIX extension the prime example). It is a one-time operation during installation on a project. After that, no events, no commands, etc. but for most scenarios is much simpler.

Merging a common project with build variations in .NET MVC

I have a .net mvc site that should be published to a lot of different customers, and thus vary slightly depending on the target.
Is there any way to set up the core project structure, e.g. (simplified):
views
models
controllers
assets
bin
and make a merge at build time with whatever variations the current target might have. For example:
core project:
views
view1.cshtml
view2.cshtml
(removed rest of the folders for brevity)
customer 1 target:
views
view2.cshtml
view3.cshtml
desired merge result:
views
view1.cshtml (from core project)
view2.cshtml (from customer 1 target)
view3.cshtml (from customer 1 target)
The same rule should apply to controllers, binaries etc.
I would either use multiple projects, nuget, or use source control. I will talk about these ideas below, but in no particular order. By the end I may include a preference towards one or the other.
First idea I'll talk about is to use multiple projects. Create your base project, let's call it WebBase. Create your core website that you have talked about. Next create Customer1 website, if you create Customer1 as an empty website you will need to recreate the folder structures in WebBase or you cane create it the same as you did with WebBase and remove all the files(do this from within Visual Studio); either way you end up with the folder structure with no files. I would recommend keeping web.config,packages.config, Properties folder with AssemblyInfo.cs. Then you will add the files from WebBase, but don't just add them normally. For illustration's purpose let's do the Home Index View: Expand the Views Folder in Customer1, Right click on home, choose add, choose Exising Item, browse out of Customer1 and then in to WebBase/Views/Home and single click index.cshtml, now notice the drop down on the button? click that and choose "Add as Link". Now do this for all the files in WebBase! It will seem cumbersome to choose "add as link" every time, but if you just click add, it will copy the file and updates won't propagate from WebBase to Customer1! Also, you will see things like remove from project vs delete (with prompt about permanent deletion).
Second thought would be to create a nuget package for WebBase and you can than install it as a package, the benefit of this approach would be versioning and it would not require you to update every project with each little change. It would keep each project completely isolated. Down side is you would need to update each project individually to propagate changes globally. You would need to learn about nuget's nuspec file and how to include files and such. It isn't that bad, it is just XML. But you can indicate which files to include when the package is installed/updated.
Third would be source control, I know with git you can use submodule to include a seperate project (even from external repository). Which might be an option, or you could just create a WebBase branch, setup WebBase and then branch it off into each Customer's website. So create a branch called Customer1, start adding the custom customer things. Switch back to WebBase, create a new branch called Customer2... you are off to the races. Switch back to WebBase, make a global change and then merge these changes into Customer1 and Customer2 branches.
Okay, I will admit it, I would probably go with the third option. It gives you lots of benefit with little downside. It even get gives you history! If you aren't currently using source control... you should! You can install git on your machine and have the ability to check code in locally and you don't have to worry about an external repository (although I would recommend you have one as it gives you DR).
Either way, there are options available. But nothing like a single project with configurable file includes.
Good luck!
First thing that comes in mind (and probably easiest because it does not require any additional tooling) is to create core project with core functionality, views and controllers. And for each customer create separate project with custom views and controllers. Then for customer-specific project simply link all required files from core project. It can be a little tedious to link the files depending on the number, but seems doable.
Another approach could be to use tools like CAKE or FAKE, with the help of which you can script the entire build process the way you want, but I never tried doing such custom scripting myself.
Third option that I can work as well is to conditionally include files based on defined constant, but that will require editing *.csproj files. The code can be something like:
<Content Include="Views\View1.cshtml" />
<Content Include="Views\View2.cshtml" Condition="$(DefineConstants.Contains('CORE'))" />
<Content Include="Views\View2.cshtml" Condition="$(DefineConstants.Contains('CUSTOMER1'))" />
<Content Include="Views\View3.cshtml" Condition="$(DefineConstants.Contains('CORE'))" />
<Content Include="Views\View3.cshtml" Condition="$(DefineConstants.Contains('CUSTOMER1'))" />
Not sure how easy it will be to maintain it though.
I would probably consider to split the application into independent components/projects that will contain all functionality related to the component. The during the build compose components with FAKE based on what components are needed for particular client.
Your requirement is a great candidate for a custom Visual Studio Project Template.
I am thinking of preparing one big project with all the features you're deploying to whatever customer. This project also could be the trunk that you might update when a new feature or a fix is needed. Then, export the trunk-solution into a template. Then continue with VSIX project template and incorporate a wizard into it, to collect user input on a project creation. Based on the input take the appropriate action and add/remove the necessary files or enable/disable features as needed.
Or you might just keep the source files on the file system and organize them into the template on the fly - i.e., as a result of the user input during the wizard. At the end of the wizard, the template is deployed and ... voila.
What you need is super-admin section, where you could [de]activate different portions of the site, depending on customer.
There are some really good code answers here but if you're wanting an Automated Build system for every client and you have loads they could be a pain too setup.
When you could set up a script for Powershell that can do this
pseudo code
For each client site
download base code to code/
download this client's changes to code/ overwriting files
msbuild ....
copy client/ bin to build/client/
Delete code/
End For each
The answer to this question requires some innovation. So look at my solution please:
Set up the core project structure for the classes that cover Model and Controller files and then use them with technique named Add Existing Item As a Link which can share the followings:
App logic common to both apps, but not portable
User controls with no platform dependencies
Unfortunately that is not supported for razor views. So the easiest thing to copy shared views is to have multiple layout files like famous _Layout.cshtml file, one in each web app. You can also Compile your asp.net mvc Razor views into a separate dll to use them like a Reference (as shared views).
For the Assets, You can host all your style sheets (and some javascript if appropriate) from your main web application and access it from each web app.
The bin folder has core MVC dll files plus those that you add for using in your project and a projectName.dll file which will be created after building. You can simply Add/remove them by right clicking on References using Add Reference tool.

TFS Visual studio 2k13

Suppose I have a team project in tfs and every time I check in, a new build takes place. Now what I want is that suppose I add a class library to the solution then when I build it a new dll is formed for the class library. So when I check in I want the tfs to just copy only what wasn't there before in the server, i.e.. the class library dll not the whole project again.
Is this possible and how to do this
If you don't add the class library to the version control, it will not be checked in. If it is added by default, you can exclude it when you check in. (in other words, you can always select and add to the source control workspace)
So, you have a TFS 2013 server with a continuous integration build? And you want to set the CI build to be an incremental build?
Assuming you are using the TfvcTemplate.12.xaml build template, then in your build definition you should check out:
Clean Workspace [true/false] which controls whether the build agent pulls down all the code again or only things that have changed.
Clean Build [true/false] which controls if everything is built again or only things that are new (like your class library). This setting only takes effect if Clean Workspace is set to false.
More details

How to extend Visual Studio with TFS to override the Get command

I am working on a conversion from Accurev to TFS and am being blocked by Accurev's usage of symbolic links, which TFS does not work with. I have tried several methods, but they all seem to fail to work.
What I would like to do is have a file in the project/branch that lists all the linked files and folders that is stored in source control. On every get operation, I would like to read this file and link the folders and files specified in the central file. However, I cannot find a way to extend the get operation. Does anyone have any experience in extending it in VS?
TFS does not provide a way to extend what happens on a Get action. You could easily create a custom powershell or batch file that you use in place of calling tf.exe, but since Team Build and Visual Studio call into TFS directly using the Client Object Model you're not going to make this easy on yourself.
In the end everything is possible of course. You could write a custom build action for Team Build to replace the standard get operation, or create one that triggers after the standard get operation has completed. You can write a vsix visual studio extension that replaces the standard Get operation everywhere in the menu's of Visual Studio and get to a something that could be considered workable. But I would not recommend this. It is far from standard and it is far from sustainable. You'll have to unwire so much default behavior in Visual Studio (that checks out files that are changed, adds files to source control when they're added to the project file etc etc etc).
SourceSafe used to have this feature as well (it was called pinning) and Microsoft removed it when they created TFVC. They now recommend you use branching and merging to synchronize these files across multiple projects, making sure that the source structure in Source control is the same as the ones on disk during build.
You can also make use of the Add-as-Link option in your project files. This allows you to keep the original files in their original location, but MsBuild will understand that in the project structure this file actually lives somewhere else. Or package the linked files up in a NuGet package and use the Dependency Management using NuGet guide to help you place the files in the right location during build.
And finally, you can get very creative using Workspace Mappings, many people never get further than mapping $/project -> $(SourceDir), but in essence the workspace mapping is like the file you describe. A way to layout your sources from Source control to disk. You could do:
$/Project/DEV/MyProject -> $(SourceDir)\MyProject
$/Project/Shared/FilesToCopy -> $(SourceDir)\Shared
And you can even add files from other projects in the same collection:
$/AnotherProject/Shared -> $(SourceDir)\MoreShared
And something not many people know, you can layout individual files:
$/AnotherProject/CompanyAssemblyInfoItems.cs -> $(SourceDir)\CompanyAssemblyInfoItems.cs
The only thing you cannot do, is map files to be children of an already mapped folder. In that case you might need to have the workspace mapping do the fetching of the sources and then a .targets file that you include in your .csproj file to do the copying of files.

Categories

Resources