I have a WCF service with the service file as - Serivce.svc
Here I can read incoming headers using the WebOperationContext.Current
The code from the Service file access a data access utility layer which makes other calls; I need to to do some work in the data access layer based on the header passed in.
However, the WebOperationContext.Current is null here.
How do I get around this?
From your question, it seems your "data access utility layer" is dependent on information that was passed to the service through the headers. Make this explicit, preferably through an interface so it's easily testable. Something like this:
public class DataAccessLayer(IMetaInfoFromHeaders requiredInfo)
{ /* implementation */ }
(Alternatively you could just have the IMetaInfoFromHeaders be an argument for just one or a few methods in the DAL, if that seems better - this depends on the specifics.)
Your service is responsible for processing the message. It should extract the information from the headers, and pass it to the DAL using an object implementing IMetaInfoFromHeaders.
Bottom line: don't make the DAL dependent on the WebOperationContext.
Related
I am writing a dll that is referencing to some WCF service.
The dll is functioning as a Gateway of the service and all calls are going through it.
Probably there can be concurrent calls .
I have referenced the service but now I cannot decide how to write the wrapper functions correctly.
Is there some example or best practice for this functionality.
I would make wrapper that matches the web service interface. It would also be a good idea to wrap up all of the objects exposed. Basically create a proxy. What I find really useful for this type of thing is to create an interface that matches the API and implement that. That way, you can create a dummy version of the DLL for testing without the overhead (or potential costs) associated with the WCF call. It would also make it much simpler if you need to replace the WCF call with an alternate provider in the future.
As an example, lets assume that we have an WCF service to an external provider for processing a payment. Something like this:
void ProcessPayment(float amount);
We could easily hook this into our code. The problem is that a simple change to the interface would result in us having to make changes everywhere the code is referenced. The same would be necessary if we changed providers to someone else, even if the interface was almost identical. Adding something like a simple interface:
interface IPaymentProvider
{
void ProcessPayment(float amount);
}
Would completely decouple our code from the WCF service. We could easily build a class like this:
class PaymentProviderAWrapper : IPaymentProvider
{
void ProcessPayment()
{
// Call the WCF service
}
}
That we could load dynamically with a factory or dependency injection framework like Spring.NET. Changing to a provider B would be as simple as creating a new wrapper:
class PaymentProviderBWrapper : IPaymentProvider
{
void ProcessPayment()
{
// Call provider B's Native DLL
}
}
Switching your code from provider A to B would be as simple as changing a configuration setting.
Even if we compiled the library directly into our code, all we would need to do is change the construction logic to use the new library. The rest of our application would not change at all. Just a simple recompile.
In response to Graymatter's answer I don't see what the difference is between calling a service wrapper which exposes the same calls and then forwards the calls to the real service, and just calling the service, assuming a one-to-one mapping on individual calls and no change in transport binding.
The only reason you would want to create a wrapper in the first place is that the interface exposed in some way does not meet your requirement on it's own. There are several reasons you may want to do this but a few common ones:
Protocol translation - the service is not exposed across the correct transport binding for your needs
Service Composition - the interface operations are too granular and don't represent business-level operations.
Authentication - perhaps you require an authentication layer on top of the endpoint you are consuming.
So how to wrap the service endpoint depends on why you want to wrap the service...
From .NET(C#) code, we are invoking a Java Web Service.
Its a SAOP request. The Java WebServices are developed using Axis 1.4.
Following is the sample code that makes the java web service request:
private string GetUserInfo(string strEID)
{
string strEmpData = string.Empty;
GetEmpInfo.EmpProxyService objEmp;
try
{
objEmp = new GetEmpInfo.EmpProxyService();
strEmpData = objEmp.searchByEID(strEID);
}
catch (WebException ex)
{
}
objEmp.Dispose();
return strEmpData;
}
Now, we have a change request which requires passing some additional information - a name_value pair to the java webservice.
How can we achieve this ?
Can I pass the information in HTTP/SOAP headers?
Changing the method signature and adding the additional info to pass the info is not at all the good idea I guess.
EDIT: Its basically we want to add the logging inforamtion of who are all consuming the web services. Once the java webservice request is processed successfully, we will log the usage information along with the source of the request (from webappln/windows appln/flex client).
We want the clients to send its unique id to identify it. Since this has nothing to do with the business logic, can we add it meta-data info...say in headers.
If you have control over the service signature, I would actually suggest that you change the signature of this web service, or add another method that takes the additional arguments. When you're using a high-level language like C# or Java, the tendency is for the web service framework to abstract the entire SOAP stack away from you, and leaves you dealing with just the plain objects that eventually get serialized to make the method call. With only the argument objects exposed, it can be tricky to try to inject additional stuff into the SOAP message, if it's not part of the actual method signature.
There are usually ways to manipulate the SOAP message by hand, but I would probably shy away from that if possible, as editing the SOAP message by hand goes against the point of using a serialization-driven framework. That said, if you have no control over the service method, and the group in control of it needs you to pass additional data outside of the soap objects, you might be stuck messing with the SOAP message by hand.
If you want to add some future proofing to your services, I would suggest passing a full-fledged object rather than a single string or primitive value. In your object, you could include a key-value data store like a HashMap or Dictionary so that additional data can be passed without changing the signature or schema of the web service. With key-value data, documentation becomes important because it's no longer clearly specified data types or parameters.
You can use SOAP headers but I would rather not go that route since the headers have no business meaning. Rather change the signature and use request and response objects.
SearchByEIDResponse GetEmpInfo.EmpProxyService.searchByEID(SearchByEIDRequest)
Ths makes any changes less painfull and prevents huge parameter lists.
How you pass information to a web service is dependent on the methods that web service exposes. What language that service is written in is inconsequential to you as the consumer. IF the Java web service requires a name value pair to retrieve some data than a method signature will expose that.
objEmp.searchByEID(strEID, strVal1, strVal2);
That said you as Eben indicates you are better off using request and response objects to keep your parameter lists short. When to use these more complex types comes with experience i.e. don't use a request object from the get go if you need to only pass a single string value, but use a request object if you need to pass 50 string values.
If you have multiple webservices and don't want to change all methods (which is reasonable), a SoapExtension is the way to go http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx
You write your soap extension class on the client, declare it in the web.config and you're done.
I have some member functions in three custom classes already created in my service. My objective is to use these custom classes on the client side to access the the member functions in the service. How do I expose these classes with all the member methods in them to the client?
I created these three classes in my service and marked them as "DataContract", and the member functions as "OperationContract". I created an Interface that defines these custom classes as OperationContracts returning an object of each of the classes through implementing them on a separate class.
Unfortunately, I couldn't achieve my objective because two of the classes have a constructor that takes some parameters, whereas the class with no constructor was accessible on the client side but I couldn't see the member methods in the class.
I need your hints on what to do.
That won't be easy to do. One way would be to share the DataContract-decorated types between the WCF server and its clients, i.e. add a reference to your service assembly in the client project and bind the service reference to that assembly reference.
However, that breaks contract implementation independence, as the exact same service assembly will need to exist on both the client and the server, and be kept synchronized every time it changes.
See here for more details.
By default and by design, WCF will only share contracts between client and server, e.g. your services ([ServiceContract]), their methods ([OperationContract]) and the data structures they operate on ([DataContract]).
WCF is a message passing system, so all the client and the server share in terms of the data being passed around is a XML serialized message format. When you add a service reference, the client-side proxy will generate a class for each [DataContract] that will look identical in XML serialized format - only the data is being moved back and forth - no behavior (no methods).
Basically, if you want to expose functionality, you need to have a service method decorated with a [OperationContract] attribute. Methods on your data classes will never be visible to the client - and that's by design.
If you control both ends of the communication and both are .NET based, you can "trick" your way around this limitation:
put all your service and data contracts into a separate class library assembly
use a reference to that common, shared assembly to create your service
before you do an Add Service Reference, add a reference to that common assembly on your client
In that case, the WCF runtime will reuse existing types from that common assembly, instead of re-creating them from the service description. And since that assembly contains the shared code that the server also uses, your classes also have their methods present.
It works ok in a .NET only scenario, but it's really kind of a dirty trick behind the proper service separation facade.
I am using MVC 3. I am trying to get my head around the services layer and the service. I am currently working through the sample app that comes with the DoFactory source code. This question is based on the sample application, but in general.
There is a service layer (WCF) that exposes a set of service methods. The service layer implements a single point of entry (the Façade pattern) through which all communication with the layers below must occur. The Façade is the entry point into the business layer and exposes a very simple, course-grained API.
Lets says I am trying to get a list of clients, then in the MVC controller it will call the repository's GetCustomers method, then this will call the service layers GetCustomers method.
I think I am a bit confused here. Is this application architecture correct? Shouldn't the controller call the service layer's method and then this call repository's method. I always thought that the repository was always the last method called to get data?
Please can someone help clarify this?
Your architecture is correct.
I always thought that the repository was always the last method called to get data?
Yes, in your case the data comes from a WCF service but it could be anything: SQL database, XML file, ...
My Situation:
The data request chain of my application looks like this:
(Client) -> (WebService) -> (SQL or OLAP Cube)
The client is a Silverlight Application that uses a generated proxy to communicate with a WCF webservice. Which in turn does authorization and accesses SQL DB's and OLAP Cubes using a DAL component, basically it just forwards the requests. Therefore, each method exists in four different places:
// WCF Webservice interface and implementation (used by client)
public interface ICatalogService
public class CatalogService : ICatalogService
// DAL interface and implementation (used by webservice)
public interface ICatalogDataAccessLayer
public class CatalogDataAccessLayer : ICatalogDataAccessLayer
Now my question, where should I put documentation to clearly specify these methods? On class or interface level, on the DAL or on the webservice?
My thoughts so far:
I would say it makes most sense to write the method specs on the interface, because it is the contract that is being consumed. However I don't see an advantage between webservice and DAL in my specific situation:
I am the only developer, there is no separate webservice-guy or client-guy that needs the docs
This is a closed architecture, the webservice is not public
Everyone working on this project in the future, will have access to all components of it (and will find the docs, wherever they are)
So, what do you think about it? Where should I put method-level documentation in this case?
I would think that most people would expect a web service to be documented more heavily than a DAL (especially if the DAL is mostly generated code: I'm guessing so as these are pass-through methods). I would add a pointer to the web service documentation in the DAL comments for those who work with it in the future.
The reason is twofold. First, the Web Service is the real point of interaction (and thus the point where more clients might be added, which means having the service documented is a plus). The second is that the DAL really doesn't sound like it provides "added value" over the Web Service (in the configuration described), so pointing back to the real point of interaction and value makes sense.
If the DAL was ever threatened with reuse by another client without the web service layer... obviously that changes things to lean the other way around (or to automate duplicate comments).