Generate WCF proxies as part of the build process - wcf

I'm writing a WCF service which is going to be used extensively within our company, and I'd like to generate WCF client proxies as part of the build process and package them within an assembly so that clients of the service don't have to repeat this process on their end numerous times. Is there any way that anybody knows of to accomplish this ? Are there any pre-existing build tasks for MSBuild ?

I was trying to solve the same problem. Here's what ended up doing.
In the .csproj, under AfterBuild target, add a task to fetch the SDK path, and use the Exec command to run the svcutil.exe. I had to use " because the path contains spaces.
<Target Name="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="SdkPath"/>
</GetFrameworkSdkPath>
<Exec Command=""$(SdkPath)bin\NETFX 4.5.1 Tools\svcutil.exe" $(TargetPath)"/>
</Target>

Here's what I wound up doing:
1) Create the project that has the service for which I want to generate client code
2) Create an MSBuild task that does the following:
a) Takes the compiled WCF Service assembly, runs svcutil.exe on it to extract XSD and WSDL metadata for all the services in the Service assembly.
b) Runs svcutil.exe again, this time on the extracted XSD and WSDL files to generate a .cs file containing the client
c) Run csc.exe to compile the generated client code into a separate assembly.
3) Insert the MSBuild task into the 'AfterBuild' target of the project containing the service.
Now every time I build the service, I get an automatically generated assembly that contains the client code that multiple other projects in our company can reference, without having to re/generate the same Web Reference in multiple projects. They can just reference a single assembly, and update more easily, having only to update one line in a project file rather than multiple files generated by the web reference generator. If anybody's interested, I can send them the code for the MSBuild task and the XML snippet for using it.

I am not aware of any built-in tasks, this is how I do it:
Create a project, generate the proxy class via svcutil and add it to the project.
Create an MSBuild script that (1) calls svcutil and overwrites the above class and (2) builds the project.
Would that not achieve what you want?

Look at T4 templating, and projects such as T4Toolbox

Why not simply create a separate, class library project. In that project, use "Add Service Reference" for each of the services you need.
Other code can then simply use the classes in the class library.

Related

ClickOnce app built via Jenkins throwing CS1704 - An assembly with the same simple name {whatever} has already been imported

I have a winforms app, which is deployed via click-once publishing.
Assuming my tests are correct, the only way to have this same app installed more than once in the same machine, is the each publish be made for a different Assembly Name.
My problem is that I am running the msbuild via jenkins, and, to accomplish the above, I would add /p:AssemblyName={whatever}, which will rename all assemblies generated by the build to this same {whatever} value. If the output of my build is 1 exe and 5 dlls, all 6 files will be named {whatever}.
Which in turn raises CS1704: An assembly with the same simple name {whatever} has already been imported.
Is the only way out of this to perform all csc.exe calls that msbuild generates, myself, and see if I can set different assembly names per project ?
Or are there other ways to solve this ?
The problem here is that every property passed to MSBuild as a command line argument is considered a global property and will override the property on all projects built in that invocation. The solution is to introduce an intermediate property that only the "main" project consumes.
Edit the app's csproj file to include this (in the place where AssemblyName is already defined - assuming here that WindowsFormsApp1 is the name of the application):
<AssemblyName>WindowsFormsApp1</AssemblyName>
<AssemblyName Condition="'$(OverrideAssemblyName)' != ''">$(OverrideAssemblyName)</AssemblyName>
you can then use the msbuild commands using /p:OverrideAssemblyName=AnotherName without creating conflicting assembly names on referenced libraries. The property is still defined globally, but only one project consumes it.

TFS 2010 - WebDeployment - indirect referenced assembly missing

We've got the following problem:
solution-structure:
AutofacRegistration
References: Repositories.dll
WebApplication
References: AutofacRegistration.dll
In our web application we are referencing the AutofacRegistration.dll and this assembly references Repositories.dll. Repositories.dll is instantiated on runtime per IOC-Container.
When we build the solution in VS2010 and browse the web app everything is working fine, as expected.
When we use our build server(TFS 2010) und use the web deployment, the Repositories.dll is missing the web-app\bin folder and we got a runtime exception(when we want to instantiated a class in Repositories.dll)
But Repositories.dll is in our drop location, so the web deployment target does not copy this file, any ideas how to solve this??
Have you tried a copy task from the BuildTemp location to where your Web Deployment Project can pick up the file it needs?
<Copy SourceFiles="$(OutDir)\Repositories.dll" DestinationFiles="web-ap\bin\Repositories.dll" />
The paths will need modified but you get the idea. I do a similar function in MSBuild to move a dll for our installer to pickup.

Castle include WCF hosting

In our WCF solution we have one ConsoleHost (console application not class library) project and one WasHost Project. We use the Consolehost hosting for Dev environment and WAS hosting for production.
Now there are a number of .config files that are included using "include uri=file://services.config" in the Castle section of ConsoleHost project. I don't want to make a copy of this services.config file in the WasHost Project.
Is there a way to include files from other projects without making local copies of them? Or happy to hear other better ways of doing this.
Thanks
Ravi
You could do this a couple of ways.
One is to simply add a link to the source file from both projects as described here.
Alternatively you could embed the config into one of the common assemblies (Build Action=Embedded Resource in the file properties) and then use Castle's ability to include embedded resources. E.g.
<include uri="assembly://AssemblyName/xxx.config"/>

How to get Obfuscated Build(Smart Assembly 5) into Drop Folder(TFS 2010)

I've been tasked with obfuscating and auto building our projects. I have the two working great independant of one another, but I need to find a way to get the obfuscated build into the drop folder set in TFS2010.
In my .vbproj file my MSBuild code looks like this:
<PropertyGroup>
<PostBuildEvent>"C:\Program Files\Red Gate\SmartAssembly 5\smartassembly.com" /build "$(ProjectDir)DBManager.saproj" /markasreleased </PostBuildEvent>
</PropertyGroup>
The problem is it's building the unobfuscated code and putting it into the drop folder.
Any ideas would be greatly appreciated!
Thanks,
Larry B.
I usually perform obfuscation after all compilation is complete. I then will have a subfolder of the drop folder (i.e. DropFolderPath\Obfuscated) and output each one after running my obfuscation utility into that subfolder. That allows the team to have both the unobfuscated assemblies and a copy of the obfuscated assemblies.
I also do it outside of MSBuild. I use InvokeProcess workflow activities in the broader Windows Workflow Foundation-based build processt template.
EDIT: I actually put together a blog post for how to integrate SmartAssembly into the TFS Build process here: http://bit.ly/SmartAssemblyTFS

Custom MSBuild task with dependencies

I have written an MSBuild task that makes use of third-party assemblies.
When I use the task in my project, MSBuild complains that it can't load the third-party assemblies (not surprisingly).
Where should I place the third-party assemblies so that they are available to MSBuild. I tried adding project references to them without success.
I'm not sure if I expressed my problem very well, but now I've found the solution.
In my .proj file, I reference my custom task with the following syntax...
<UsingTask AssemblyFile="..\lib\MyCompany.MSBuild\MyCompany.MSBuild.dll" TaskName="CreateDatabase" />
My CreateDatabase task relies on various 3rd-party assemblies. However, some of these are only referenced via reflection, so weren't included by default in the folder "..\lib\MyCompany.MSBuild".
I had been trying to get the task to work by placing the required assemblies in the same directory as the .proj file invoking the task.
However, what I should have been doing was putting the assemblies in the referenced task directory "..\lib\MyCompany.MSBuild\".
Simple!
You could add them to the GAC (Global Assemby Cache). This only works if it is strongly named.
You could also make sure that you have marked them with copy local = true when you added the reference in the project.