Merging WCF references via ILMerge - c#

I have a WinForm project in Visual Studio 2017 where I have created a WCF endpoint reference from a service's wsdl file.
My project also uses several 3rd party dlls.
I want my project to be a standalone exe file that does not require installation, so I use ILMerge to package my dll files into a single exe file.
When running my compacted exe, I am getting exceptions about missing references to the WCF project endpoint:
Could not find default endpoint element that references contract in the ServiceModel client configuration section.
I tried looking up how to add WCF references via ILMerge, but I couldn't find anything relevant.
I also cannot find anything WCF related in my project's bin output folder.
My current usage of ILMerge is via cmd:
ILMerge.exe /t:winexe /out:target.exe /targetplatform:v4,<.net v4 path> output.exe dll1.dll ... dlln.dll
I am looking for a way to add the WCF references to the standalone exe via ILMerge, or locating the WCF reference outputs generated by Visual Studio in my project's bin out directory.
Solution
Following Abraham's comment, I found a way around the 'service reference' issue.
I used Svcutil.exe to generate the definitions to my service, and manually set the binding to it like so:
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.Transport;
EndpointAddress myEndpoint = new EndpointAddress(SERVICE_URL);
SoapServiceClient client = new SoapServiceClient(myBinding, myEndpoint);
Now everything gets packed when using ILMerge.

By adding service reference, there are also some extra configurations generated in the configuration files. Therefore, it might cause the failure of packing the project. Alternatively, we manually copy the System.servicemodel section to the new project.
I suggest you change the way to consume the service. your project seems that you call the service by adding service reference. this will bring some other class libraries and references, which resulted that it is difficult to pack the project.
Please consider the below way to call the service.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-channelfactory
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/channel-factory
it fully encapsulates the required class library in the main project.
Feel free to let me know if there is anything I can help with.

Related

Do binding redirects in app.config for class libraries do anything?

The VS solutions I often work with consist of a single executable project (console app, web app) and many class library projects that are all referenced by the executable.
When working with NuGet and installing packages, there's often an app.config file created for each project, usually containing nothing else than a list of binding redirects that consolidate versions of referenced assemblies. Sometimes there's some third-party library-specific content (like Entity Framework config section), but let's leave that aside for now.
When I build the solution and use the binaries of the main executable project, I see all the class library project assemblies in the build output together with the corresponding *.config files (the app.config file gets renamed to AssemblyName.config when built).
When launching the main executable, do the config files of the class library assemblies take any effect? Or is it just the app.config file of the executable that has an effect in this case? What if there are some binding redirects set up on some of the class library projects, and some different binding redirects set up on the main executable project — How are these combined, which take priority?
I've tried to research this online and from what I've read, it looks to me like the app.config files for non-executable assemblies are useless (with regards to binding redirects). Can someone confirm this or elaborate a bit more on the topic?
If it is that way, is it actually undesirable to have these app.config files created by NuGet in class libraries if they contain just the binding redirects? It feels to me that NuGet shouldn't create those binding redirects for class library projects, as it will only increase the confusion about what settings are actually applied.
I found these existing Stack Overflow questions on the topic, but their accepted answers are actually contradictory even when they're marked as duplicates of each other.
Why NuGet adds app.config with assemblyBinding to LIBRARY projects during a NuGet package update?
Is the bindingRedirect .config file needed or all assemblies in an application?
The accepted answer to the first question mentions that app.config files are actually used during compile-time, which means they could have effect. Sources like MSDN and MSBuild source code are cited there as a proof it's used during compile-time. Unfortunately, I'm not proficient enough in MSBuild to understand how it's being used, and if it's really a valid argument.
Can anybody describe an example scenario to prove that an app.config with binding redirects for a class library can do anything?
I have multiple applications with similar setup - Web application referencing multiple library projects each having their own nuget packages etc., Based on my personal experience the assembly bindings in the library projects are not considered during run time.
The bindings specified web or app config in the root application (web/console) is that only matters. All my library projects are setup with "Copy to Output Directory" setting as "Do not copy" for the app.config file - that way my output folder is not cluttered with dll and their config files.
Here is the link which says how the assembly is loaded and where is it being searched and the sequence of it. No where in the article they talk about individual project config files.
Hope that helps.
According to this old msdn article:
An application configuration file is an XML file used to control assembly binding. It can redirect an application from using one version of a side-by-side assembly to another version of the same assembly. This is called per-application configuration. An application configuration file applies only to a specific application manifest and dependent assemblies. Isolated components compiled with an embedded [ISOLATIONAWARE_MANIFEST_RESOURCE_ID] manifest require a separate application configuration file. Manifests managed with CreateActCtx require a separate application configuration file.
So only dll's with the ISOLATIONAWARE_MANIFEST_RESOURCE_ID set actually use an independent application config, otherwise it's deferred to the main process config file.
For more info on what ISOLATIONAWARE is you can read this other MSDN article that goes more in depth.
ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It
should be used if the dll wants private dependencies other than the
process default. For example, if an dll depends on comctl32.dll
version 6.0.0.0. It should have a resource of type RT_MANIFEST, ID
ISOLATIONAWARE_MANIFEST_RESOURCE_ID to depend on comctl32.dll version
6.0.0.0, so that even if the process executable wants comctl32.dll version 5.1, the dll itself will still use the right version of
comctl32.dll.
The answer is maybe. Depending on the type of project the library file is. Some library projects run in contexts where the library's config file is respected (e.g. Azure Web Roles), but that is not the norm.
See my answer here for more details.
Generally there is only one configuration file and thats the configuration file of the executeable (.exe.config, web.config).
Any assembly redirects have to be placed in the configuration file of the executable.
Configuration files of dlls need to be loaded manually using the ConfigurationManager class. See also this question Equivalent to 'app.config' for a library (DLL)
No, only the app.config of the executable will have effect. For example, if you have a console app hosting a WCF service, and in your WCF service you make use of, for example, ConfigurationManager.AppSettings, the AppSettings will come from the console host app.config file. If you spin up another console application (ConsoleClient) to try connecting to the ConsoleHost, then in the parts where the ConsoleClient can be said to be "executing" (for example in its main method), it will use ConsoleClient's app.config, but as soon as it begins using the WCF service, the WCF service will delegate to use ConsoleHost's app.config. (Note that this last point is more relevant to the details behind WCF though.)
Surprisingly, msdn provided this great source:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?forum=wcf

ILMerge into nuget package causing issue with Parameter Type Mismatch with consuming project

I have a service dll, which has a reference to System.Web.OData (from Microsoft.AspNet.OData.5.9.0)
The service dll has an exposed method which takes in an OData.Delta<>
This service dll when compiled is ilmerged, so it has this "version" of Data embedded.
Now the consuming application, also has a reference to the same OData, however, it comes from a corext, globalized cache.
However, when the consuming application, attempts to call the method that has an OData.Delta<> parameter, it complains that it cannot convert from ConsumingApp.OData.Delta to ServiceDll.OData.Delta.
How would I go about making sure that the parameter uses the actual proper "version" of OData.Delta so that they do not conflict?
I can't seem to find like.. a NameSpace.For.ServiceDll that would enable me to specifically target the OData.Delta that is embedded in the ilmerge
you have to install ms odata client for visual studio create a new odata client class, an add in http uri metadata de correct http. After that click on the file and run custom tool option download de latest metadata
Sorry I understood that had problems with odata schema. The error you expose, if I understood well you are using ilmerge for combine various project and reference again the library combined. I think:
you can add the namespace with a surname, for example:
import reference1 = microsoft.data;
import reference2 = ilmerge...;
so you can use them in code like reference1.class1 and reference2.class1
Hope this help you

Copy service reference from one project to another project in same solution

We have one service reference in one project of a solution. I am trying to move this service reference to new project in same solution. But adding the service reference in new project using URL present in the service reference of old project is throwing 404 error. I am not sure where is this service hence do not have it my IIS.
I tried to copy all the files and adding them to source control. like copy paste but then it has some auto generated code under reference.cs which generates all classes. They have old namespaces and might have to change it to new namespace manually. So, not sure if this can cause some other issue as I will be manually updating the auto generated code.
Is there a way to add this service reference in my new project?
option 1 - find the url by debugging the first project
Assuming that the first project accesses the WCF service correctly, you can debug it to the point where it makes the service call and look at the the remote address in the watch
var url = currentProxy.Endpoint.Address.Uri;
option 2 - add reference to the project thats already working
add a wrapper class that makes the WCF call in your original project and then add project reference of your original project to the new project. now you can you use the newly created wrapper to access the WCF service from the new project via the wrapper

"Method Not Found" Error at Run Time (Calling method from different project)

Problem
I have a solution that contains 10+ projects. The most important being:
SharePoint 2013
WCF Service
Windows Service
Various test, Python, and Powershell related projects
I noticed that the projects contained a large number of models/classes that were repeated throughout all of the projects. To cut down on repeat code, I created a new project to house shared code. Unfortunately, I now receive this error at run-time:
"Method not found: [Name of method you tried to call]"
for any method in the shared project. It is worth noting that I have:
Added a reference to the new project for all project's that use it
This error ONLY occurs at RUNTIME
I am able to get the SharePoint solution to work if I add the shared project as an 'Additional Assembly' in the 'Package.Package' configuration file. However, this adds the shared project to the Global Assembly Cache (GAC), and still suffers from issues each time the shared project is updated.
Question
How can I deploy individual projects that reference code in the shared project without them blowing up at RunTime?
RELATED:
WCF Method not found after signing an assembly
My shared assembly is signed (required to work with SharePoint)
Fault Exception - Method not found
Trying to deploy a GAC install; Prefer to deploy in BIN folder
https://stackoverflow.com/questions/7578538/method-not-found-on-runtime
Drag and drop a DLL to the GAC ("assembly") in windows server 2008 .net 4.0
Methods Attempted
WCF: [RESOLVED]
Verify (and remove) DLL from Global Assembly Cache
Verified that project is "added as a reference" to WCF Project
Turning "Copy to Local" to true, and deploying WCF w/ other project's DLL
Any Assemblies the shared project relies on must also be deployed?
Not sure how "web.config" values are accessed/modified by shared project's classes now that it's a DLL?
See here for GAC related help: Drag and drop a DLL to the GAC ("assembly") in windows server 2008 .net 4.0
Windows Service: [RESOLVED]
Same steps used for WCF Service
SharePoint: [RESOLVED]
Open SharePoint "Package.package" file
Select the "Advanced Tab"
Under "Additional Assemblies", click "Add" and "Add assembly from project output"
Select the source project
Select "Web Application"
Click "Okay"
SharePoint Notes: Deploying as "Web Application" instead of "Global Assembly Cache" appears to be deprecated, but I receive the most consistent results with this option. When deploying the SharePoint Solution, the command needs an additional flag to suppress this warning:
SharePoint 2013 Management Shell:
Update-SPSolution
-Identity [NameOfProject.wsp]
-LiteralPath [PathToWSPToDeploy.wsp] -GACDeployment
**-FullyTrustBinDeployment**

Including a service reference from a class library

I have a C# class library and a startup project (a console app). The class library includes a service reference to a web service. When I try to run the project, I get an InvalidOperationException because the startup project isn't reading the class library's app.config, and it's ignoring the service reference. To get it working, I'm forced to add the same service reference to the startup project. Is there any way I can avoid this? Can I make the startup project recognize the class library's service reference and app.config without having to copy it to the startup project?
I've tried adding a link to the app.config from the class library, but that doesn't work. The class library isn't very portable if it requires anyone who uses it to add that service reference to the startup project.
Think about what you are trying to do - you have two assemblies that you are building:
Library
ConsoleApp
Both of these assemblies have configuration files - I would imagine they look something like this:
Library
app.config
ConsoleApp
ConsoleApp.exe.config
When you run ConsoleApp it has no way of reading from or knowing aboout app.config from your Library assembly. The only configuration file that it knows or cares about is ConsoleApp.exe.config. Now it is possible to have configuration files reference each other but this is not the proper solution for what you are trying to do.
Since your Library assembly has no entry point, it will never be loaded into an AppDomain. Since it will never be loaded into an AppDomain its application configuration file will never be used.
What you ought to do is reference Library in ConsoleApp via a project reference. Then move all the relevant configuration data from app.config into ConsoleApp.exe.config as this is the configuration file that will be used by your application.
This will allow you to have to two things you need to invoke methods on your web service
The code in Library that can send and receive SOAP messages.
The configuration metadata that is required by Library to function.
An alternative to using a service reference in the class library and then copying the config would be to use build events that call svcutil.exe. The thing I like about this is that you don't have to make "update service reference" when the service changes. It will be updated automatically.
In the class library, use a build event that only generates the proxy code:
svcutil.exe net.tcp://localhost:3315/MyService/mex /noConfig
In the application, use a build event that generates the config. You can use the /mergeConfig option to merge it into an existing app.config.
svcutil.exe net.tcp://localhost:3315/MyService/mex
/config:App.config /mergeConfig
If you don't want to get a build error if the service is not running, put this in your project file and you will get a warning instead of an error:
<Target
Name="PreBuildEvent"
Condition="'$(PreBuildEvent)'!=''"
DependsOnTargets="$(PreBuildEventDependsOn)">
<Exec WorkingDirectory="$(OutDir)"
Command="$(PreBuildEvent)"
ContinueOnError="true" />
</Target>
You just need to copy the config key, pointing to the service, from your class library config file to your console app's config file.
You can copy the relevant portions of the app.config from the class library's configuration into the app.config for the console application.
Alternatively, if you're really trying to make this truly portable, you'll need to think about another way of referencing the address for the specific service reference from within the class library.
I'd think it more confusing if you had multiple configuration files running around.
If a library has configurable items, I would fully expect to have to put that configuration in my config file to properly consume the library.

Categories

Resources