Accessing web services uniformly - vb.net

I have three web services, which were developed by three different vendors and have different URLs; input parameters and output parameters. They are all ASMX web services. They are used to delete records from third party relational databases e.g. I supply a personID and a person is deleted from one system and everything linked to the person. In another system I supply an order ID and everything linked to the order is deleted.
I have several options:
Create a single wrapper class, which is responsible for accessing the web services; supplying common input parameters and accepting common output parameters. This class would have lots of responsibilities.
Create three wrapper classes i.e. one for each web service
Modify the proxies generated by Visual Studio
Which way is best?

I would recommend allowing Visual Studio to automatically generate the appropriate proxy classes. I would then implement a wrapper class for each web service so that all of the wrapper classes could implement the same interface. For instance, you may make a common interface that looks like this:
Public Interface IPersonBusiness
Sub DeletePerson(personId As String)
End Interface
Then, lets say you had two web services. The first, we'll call it WebService1, has a Delete method which takes a person ID followed by the deletion time. The second web service, we'll call it WebService2, has a DeletePeople method which takes an array of person ID's. We could wrap both of these web services using the above common interface, like this:
Public Class WebService1Wrapper
Implements IPersonBusiness
Public Sub New(proxy As WebService1)
_proxy = proxy
End Sub
Private _proxy As WebService1
Public Sub DeletePerson(personId As String) Implements IPersonBusiness.DeletePerson
_proxy.Delete(personId, Date.Now)
End Sub
End Class
Public Class WebService2Wrapper
Implements IPersonBusiness
Public Sub New(proxy As WebService2)
_proxy = proxy
End Sub
Private _proxy As WebService2
Public Sub DeletePerson(personId As String) Implements IPersonBusiness.DeletePerson
_proxy.DeletePeople({personId})
End Sub
End Classs
I would avoid writing your own proxy code unless you really need to. For instance, if you needed to dynamically call any web service based on some external settings which tell you the method name and parameters to pass, or something like that, then it would be worth looking into.
I would also avoid putting all of the logic to call any of the web services into a single wrapper class. Doing so will make the code unnecessarily ugly and confusing, especially if you need to add additional web services in the future.

Related

Class shared properties values are different when called from Project A then B, how so?

I have three projects, let's call them Client, Service and Execute.
Both Client and Service references Execute.
Client is a windows forms application. While first loading, it calls a shared method in a class called ParametersManager which fills four parameters in a class called Parameters.
Public Class Parameters
Public Shared Property FirstProperty As Integer
Public Shared Property SecondProperty As Integer
End Class
Public Class ParametersManager
Public Shared Sub FillParameters()
'In real scenario, I am just sending the parameters as arguments to the method.
Parameters.FirstProperty = 1
Parameters.SecondProperty = 2
End Sub
End Class
So when the application starts, it will call FillParameters from Execute.
I did debug the application, and when this method finish executing, the properties has the exact values that I gave them.
In one of the forms of the Client application, I am calling the Service which is an asmx Web Service. Service now calls a method from Execute project, let's call it UsePropertiesDoingSomething.
Public Class UseProperties
Public Shared Function UsePropertiesDoingSomething() as Integer
Return Parameters.FirstProperty + Parameters.SecondProperty
End Function
End Class
My problem is that when I call this function from the service, the properties are both equal to 0, not the values I have previously filled when the Client application first run.
How did I lose the the values? Shouldn't the values be saved in the Execute scope? How can I make sure not to lose them?
For testing purposes, I filled the parameters at the start of the Service, now when the Service calls the UseProperties the values are kept, but when called from the Client, the values are lost again.
For this purpose you have explore AppDomain and Execution context.
Shared does not means that it is shared between application or project. It is shared for specific application domain.
If same application domain load same library then it will be shared otherwise not as other application domain has it's own copy. (At least in .net it will not cross AppDomain boundry).
In your case Window Form has different Application Domain and ASMX in Web Service so it has different Application Domain so it will not be shared.

Accessing functions of added web service

I have created my own WebService in VS 2010. My project is called sampleWebService and inside my project I have successfully added/connected to another WebService this is called practiceService.
sampleWebService has just the basic Hello World auto generated code in it, however, practiceService has Web Method Functions that handle database calls such as getFirstName, getLastName,...
My question isn't how to extract the data really since I know you have to use either JSON or SOAP. I'm just wondering what I have to type into my code to be able to see the functions and methods that are in my added web reference practiceService so I can connect to them.
Or maybe this is accomplished by using JSON or SOAP
Right now my code for my sampleWebService page is just as is:
<ToolboxItem(False)> _
Public Class Service1
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function
End Class
You can have a look at the proxy class that was generated when you added the web reference. Also when you create the object of practice service it will give you access to all the web methods exposed in that web service.
To access the web method you have to do something like
ServerName.WebServiceName CallWebService =
new ServerName.WebServiceName();
String sGetValue = CallWebService.MethodName();
Label1.Text = sGetValue;

Running function of one application from within another application

I've got two standalone applications:
First one:
Namespace FirstApplication
Class MainWindow
Public Sub New()
InitializeComponent()
End Sub
Public Function RunBatch(Parameter as String) as Double
'Do some work
Return SomeValue
End Function
End Class
End Namespace
Second application:
Namespace SecondApplication
Class MainWindow
Public Sub New()
InitializeComponent()
End Sub
Public Sub RunBatch()
'Call RunBatch() from first Application, get show the result
Msgbox(RunBatch)
End Function
End Class
End Namespace
Both are WPF, .Net 4.0 based. The goal is to have second application call on the first one and execute a function in it.
The key part is that both applications are used primarily independently and only occasionally second calls on the first. Because both applications need to exist as executable, I don't want to solve the problem by creating a dll of the first application - I would need to maintain both the executable and dll update to date with potentially disastrous consequences if they fall out of sync.
So the question is whether it's possible, to create an instance of first application within AppDomain of the second one and, crucially, execute functions of that instance.
I don't believe you can create one AppDomain inside of another.
Any other options you have (using WCF, or old style .NET Remoting, or crossing AppDomains) are all going to be more complicated than just making a single DLL that both applications can reference. So long as you don't change the assembly number of the shared DLL you won't have to recompile each exe if you make changes to the DLL (assuming you don't make breaking changes like changing method signatures).
Does FirstApplication have to do something to SecondApplication? Are you trying to control a feature of one application from another? If so you will need something like WCF (using Named Pipes or just a self-hosted web service). Or just trying to not have to write the same code twice? Then the simplest approach is probably to create a single DLL both applications reference.
Apparently, this can be done via reflection. The process is straightforward, though not nearly as convenient as using dll.
Public Class CalltoExternallApp
'this is the declaration of the external application you want to run within your application
Dim newAssembly As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom("Mydirectory\Myfile.exe")
Public Sub Main()
'Loads the main entry point of the application i.e. calls default constructor and assigns handle for it to MyApplication
Dim MyApplication = newAssembly.CreateInstance("MyApplication.RootClass")
'Get the type which will allow for calls to methods within application
Dim MyApplicationType as Type = newAssembly.GetType("MyApplication.RootClass")
'If calling a function, the call will return value as normal.
Dim Result As Object = LunaMain.InvokeMember("MyFunction", Reflection.BindingFlags.InvokeMethod, Nothing, MyApplication, MyParameters)
End Sub
End Class
Check also here for adding the event handlers to instances created via Reflection:
http://msdn.microsoft.com/en-us/library/ms228976.aspx

How to Allow Client-Service to Build Complex Object in WCF Service?

I made a simple PasteBin demo example of what my code looks like: http://pastebin.com/GpDhPRVm
My actual Process object is extremely complex that includes adding collections of Tasks, Documents, Workflows, etc into a Process object and setting properties through methods, etc.
My PasteBin example is as simple as I can make it to show where things break down. Including the Process object in the CreateNewProcess method in my service (shown in code below), allows the service user to automatically "see" the Process object, properties and enumerators in their instance on the client side.
<ServiceContract()>
Public Interface ICreateProcess
<OperationContract()>
Sub CreateNewProcess(ByVal newprocess As Process)
End Interface
However, it does not allow them to use any of the methods like the 'AddTask' method (shown in PasteBin example) and it also doesn't expose the Task or TaskCollection objects. Even if I decorate the methods with DataContract, OperationContract, etc they still are not visible to the client service.
This is my major issue: I need the client service to be able to fully "build" the Process object and then pass it in to the CreateNewProcess method.
Another small note: (to avoid comments asking me about it) is that I made sure that all of my properties are simple types that are interoperable since this needs to be able to work for Java - not just .NET clients.
Ok, I figured it out with a little help from a buddy of mine.
Can't use methods at all outside the .svc service class; only properties, enums and sub objects will translate down to the client. (I figured this)
Then, instead of using a Collection, you have to use a generic List type.
So, instead of this:
Public Tasks As New TaskCollection() 'where TaskCollection inherits from Collection
I needed to do this:
Public Tasks As List(Of Task)
And the client will just have to build their own array of Tasks and assign it to the t.Tasks property.
This works like a charm now: http://pastebin.com/rt8HwsXY

How do I unit test a WCF service?

We have a whole bunch of DLLs that give us access to our database and other applications and services.
We've wrapped these DLLs with a thin WCF service layer which our clients then consume.
I'm a little unsure on how to write unit tests that only test the WCF service layer. Should I just write unit tests for the DLLs, and integration tests for the WCF services? I'd appreciate any wisdom... I know that if my unit tests actually go to the database they won't actually be true unit tests. I also understand that I don't really need to test the WCF service host in a unit test.
So, I'm confused about exactly what to test and how.
If you want to unit test your WCF service classes make sure you design them with loose coupling in mind so you can mock out each dependancy as you only want to test the logic inside the service class itself.
For example, in the below service I break out my data access repository using "Poor Man's Dependency Injection".
Public Class ProductService
Implements IProductService
Private mRepository As IProductRepository
Public Sub New()
mRepository = New ProductRepository()
End Sub
Public Sub New(ByVal repository As IProductRepository)
mRepository = repository
End Sub
Public Function GetProducts() As System.Collections.Generic.List(Of Product) Implements IProductService.GetProducts
Return mRepository.GetProducts()
End Function
End Class
On the client you can mock the WCF service itself using the interface of the service contract.
<TestMethod()> _
Public Sub ShouldPopulateProductsListOnViewLoadWhenPostBackIsFalse()
mMockery = New MockRepository()
mView = DirectCast(mMockery.Stub(Of IProductView)(), IProductView)
mProductService = DirectCast(mMockery.DynamicMock(Of IProductService)(), IProductService)
mPresenter = New ProductPresenter(mView, mProductService)
Dim ProductList As New List(Of Product)()
ProductList.Add(New Product)
Using mMockery.Record()
SetupResult.For(mView.PageIsPostBack).Return(False).Repeat.Once()
Expect.Call(mProductService.GetProducts()).Return(ProductList).Repeat.Once()
End Using
Using mMockery.Playback()
mPresenter.OnViewLoad()
End Using
'Verify that we hit the service dependency during the method when postback is false
Assert.AreEqual(1, mView.Products.Count)
mMockery.VerifyAll()
End Sub
It depends on what the thin WCF service does. If it's really thin and there's no interesting code there, don't bother unit testing it. Don't be afraid to not unit test something if there's no real code there. If the test cannot be at least one level simpler then the code under the test, don't bother. If the code is dumb, the test will also be dumb. You don't want to have more dumb code to maintain.
If you can have tests that go all the way to the db then great! It's even better. It's not a "true unit test?" Not a problem at all.
The consumer of your service doesn't care what's underneath your service.
To really test your service layer, I think your layer needs to go down to DLLs and the database and write at least CRUD test.