How do I reference a file in a WCF Webservice application? - c#

I've worked on a few C# projects over the years, and generally the rules are consistent from project type to project type. But having started a WCF Webservice project, I'm finding things a bit different. I have to validate incoming XML to a schema. I've created a folder off the project root, XSDs, for storing the schemas. In previous projects, when referencing an XSD in a folder, I've used something like this:
XmlTextReader textReader = null;
XmlSchemaCollection xSchemaCollection = null;
XmlValidatingReader valReader = null;
string uri = string.Format(#"{0}\{1}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), XSDPath);
// text reader object
textReader = new XmlTextReader(uri);
xSchemaCollection = new XmlSchemaCollection();
xSchemaCollection.Add(null, textReader);
// XML validator object
valReader = new XmlValidatingReader(strXMLDoc, XmlNodeType.Document, null);
The properties for the XSD files are set to Copy Always to target folder. Normally, I get a valid path to the XSD, and things proceed just fine. But in this WCF Webservice project, the path that the XSD files get copied to is a temporary directory, and I don't get a valid path. The xSchemaCollection.Add method fails.
BTW, the XSD folder isn't in the WCF project at this point. I added a class library project (in which the above code currently resides), and that's where the folder and files are. I expected this to eliminate the temp-directory problem, but it didn't.
Any ideas what I'm doing wrong? Thanks in advance.

WCF is a very powerful framework, but one of the core concepts of WCF is that the service definition is abstracted away from the implementation details of the communication channel. This means that a WCF service has no knowledge of what XSD files are used to describe its content, or even if XSD files are used at all (a service binding doesn't necessarily use SOAP).
WCF works really well if you're trying to follow an existing protocol, or if you're trying to customize one aspect of a complex protocol in which every other aspect of the protocol conforms to web standards. However, it sounds like what you're doing is more down and dirty than that.
If you find that you must process SOAP messages directly in a way that is non-standard, WCF may not be the best tool for the job. I would recommend that you consider using other service implementation strategies, such as an HttpHandler or a good old asmx file. Asmx based web services are nowhere near as sophisticated as WCF, but it is this very lack of sophistication that makes them more flexible for non-standard protocols.

I think that if, for some reason, you have an issue to access the XSDs via the file system, then I would most likely embed them as resources within an assembly. All you have to do then is to use a custom resolver (from the sound of it, these XSDs don't seem to make use of includes/imports; it they do, the custom resolver is definitely the way to go)...

Related

.Net Web Services XML Serializer

I am using VS2015 to consume some old web services (SAP). I can import the WSDL just fine, and all the references come across ok. But, when I try and use the service, it looks like the XML output only includes properties with values. That is not working with the WSDL service. I am using SoapUI to test and it can communicate just fine with the service. Using SoapUI, if I remove some of the outbound XML in the call, it will fail. So, I think my issue is the outbound XML serialization. Any ideas on how to tackle this? Is there a way to mark the properties so they will be output even if they don't have a value? (short of putting a space or something in the field? Thanks.
This is by design to differentiate between null and empty, have a look at Suppress Null Value Types from Being Emitted by XmlSerializer

Adding Service Reference to WCF does not always create .datasource files

In some projects when I add a service reference to a WCF service, it creates datasource files for classes shared in a common class library, however in others the datasources are not created. The Reference.cs file is different where in the first case the types are from the class library and in the latter it's in the Reference.cs file it self. These are not compatible.
What is it that triggers the automatic generation of the datasource files in this case? Advanced options in Add Service Reference dialog are identical so something else must be playing tricks on me.
UPDATE: Turns out the datasource files are not needed. It's the code generated in the Reference.cs file that makes the whole difference. I can manually edit the parameters for the methods to point to the class-library, and it works. This is of course not a solution in the long run, since I have to do this every time I update the Service Reference. Hopefully someone will come along who knows the trigger of this problem.
The file is created by VS when you add a service reference. It's used to enable client UI components to bind to the models (data contracts). I don't know why they are not created for "all" services (but I guess it depends on how that service defines and uses data contracts (as in: no contract no data file)).
Here are some useful links:
https://msdn.microsoft.com/en-us/library/ee373840.aspx
What are the WCF Service Reference .datasource files?
UPDATE: You are right it should not depend on the consumed service. Here are two related links (that impliece that the files are included by VS):
http://objectmix.com/dotnet/797048-wcf-service-reference-datasource-file-name-length-problem.html
Disable automatic generation of datasources file when updating service references
So it looks like the file is created by VS, if you don't wan/need it you can exclude it by creating the proxy with svcutil.exe

Project structure for Schema First Service Development using WCF

I have WSDL and XSD as starting point. (WSDL is generated from XSD using WCSF Blue tool). From the WSDL, using a tool, the service code is generated. The project name is “Autogenerated_Service_Project”. Inside this project it will have [ServiceContract] and [DataContract] classes. It has a data contract named “EmployeeDataContract”. In the GetEmployee() service operation, this datacontract is returned to the client.
I have a business layer project named “Business_Project”. It has a method that returns “Employee” entity object.
At present, I am referring the “Business_Project” inside “Autogenerated_Service_Project”.
Business_Project.MyClass b = new Business_Project.MyClass();
EmployeeDataContract d = b.GetAssociate();
return EmployeeDataContract;
The challenge comes when there happens a change in WSDl. When the WSDL is the changed the “Autogenerated_Service_Project” will be recreated and the code mentioned above will be lost.
What is the solution to overcome this code lose?
Note: The “Autogenerated_Service_Project” is the top most project. Ideally, it cannot be referred by any other projects.
You may change the way calling Business layer(may your solution needs additional layer)
But in simple way, you can generate the proxy once, when changes happen to WSDL
handle the changes manually,Or use the tool only for new services.
If the services on WSDL are finely grained, the solution may be applicable.
This can be resolved by using Partial Classes in a different file. The code given in the question can be moved to this new partial class file. This file will persist even if the auto generated file is re-created.

Adding similar Web Services to .NET C# application

I'm new in web services and I'm developing a C# WCF service that is calling an external service from another company to get some client data (for example: name, address, phone, etc), this part is working fine so far.
The external service is based on a standard XML Schema, and other companies will have soon the same service generated from the same XML Schema, using the same name methods and returning the same type of xml file.
My first question is that after I complete this first implementation, there is any way to add “dynamically” the other external companies services, having the information of their URL/Ports/etc, or do I have to insert each on them manually as services reference in my internal service project every time I need to add a new one, then compile and re-deploy?
My second question is related with the data contract /members, my understanding is that even if they are returning the same XML files, their data contracts/members will be different, is that true? So I’ll have to make a specific code to read the information I need from their data contracts for each new external company?? If this is true I have been thinking to make a generic code to read the raw xml, is this the best choice?
While C# is a compiled language it does support pluggin architecture through MEF. You could use this and add a small plugin .dll for each of your sources.
That being said it's quite possible that all you need is a configuration list containing connection details for each of your sources and connecting to them dynamically. That will only work if they're using the exact same schema, so that the objects they serve will serialize the same for all sources. You will have to instantiate the proxy dynamically through code using that configuration then, of course.
I should add something for your second question. As long as you're the one defining the contract, it doesn't matter if their actual objects are different. All you care about on your end is the xml they serve, and that you can connect using your representation. In fact, you can generate the contract as a .wsdl document. Each of the service-implementer can then generate domain objects from that. On the other hand if you're not the one "owning" the contract, some of the sources may decide to do it slightly differently, which will cause you a headache. Hopefully that's not your scenario though.
Best of luck! :)
My first question is that after I complete this first implementation, there is any way to add “dynamically” the other external companies services, having the information of their URL/Ports/etc
Unfortunately yes, you will have add service, compile it and deploy every time
My second question is related with the data contract /members, my understanding is that even if they are returning the same XML files, their data contracts/members will be different, is that true?
If you will use auto generated every service will create different contracts. I would think about creating you own class and convert external classes using reflection and extension methods

How to make dynamically generated .net service client read configuration from another location than *.config files

I've currently written code to use the ServiceContractGenerator to generate web service client code based on a wsdl, and then compile it into an assembly in memory using the code dom. I'm then using reflection to set up the binding, endpoint, service values/types, and then ultimately invoke the web service method based on xml configuration that can be altered at run time.
This all currently works fine. However, the problem I'm currently running into, is that I'm hitting several exotic web services that require lots of custom binding/security settings. This is forcing me to add more and more configuration into my custom xml configurations, as well as the corresponding updates to my code to interpret and set those binding/security settings in code.
Ultimately, this makes adding these 'exotic' services slower, and I can see myself eventually reimplementing the 'system.serviceModel' section of the web or app.config file, which is never a good thing.
My question is, and this is where my lack of experience .net and C# shows, is there a way to define the configuration normally found in the web.config or app.config 'system.serviceModel' section somewhere else, and at run time supply this to configuration to the web service client?
Is there a way to attach an app.config directly to an assembly as a resource or any other way to supply this configuration to the client?
Basically, I'd like attach an app.config only containing a 'system.serviceModel' to the assembly containing a web service client so that it can use its configuration. This way I wouldn't need to handle every configuration under the sun, I could let .net do it for me.
Fyi, it's not an option for me to put the configuration for every service in the app.config for the running application.
Any help would be greatly appreciated.
Thanks in advance!
Bryan
Create a custom class deriving from
ChannelFactory.
Override the protected
CreateDescription method. In the
override, you need to...
Call base.CreateDescription().
Read in your custom configuration.
Create a custom ServiceEndpoint based
on your configuration. Don't forget
the bindings, behaviors, etc.
Return that custom ServiceEndpoint.
More details HERE
The following couple links talk about loading WCF Configuration settings from config files other than the app.config. May be what you are looking for but not certain.
http://blogs.msdn.com/dotnetinterop/archive/2008/09/22/custom-service-config-file-for-a-wcf-service-hosted-in-iis.aspx
http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx
Are your proxy classes deriving from ClientBase<T>? If so, then there is a constructor that accepts a Binding and an EndpointAddress. You should be able to use those instead of the corresponding configuration data.

Categories