Implementation of RealProxy ends up in an infinite loop - wcf

I'm trying to create a RealProxy in order to implement some caching and a few other functions. I've checked the Type that GetTransparentProxy returns and it looks correct, however if I call InvokeMember on it then the proxy ends up calling itself and I get a heap overflow. Please could someone point out what I'm doing wrong?
public class CachedWebServiceProxy<T> : RealProxy
{
private Type _typeOfProxy;
public CachedWebServiceProxy(Type typeOfProxy) : base(typeOfProxy)
{
_typeOfProxy = typeOfProxy;
}
public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
var proxy = GetTransparentProxy();
var result = _typeOfProxy.InvokeMember(methodCall.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, proxy, methodCall.Args);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
}
class CachedWebServiceChannelFactory<T> : ChannelFactory<T>
{
public CachedWebServiceChannelFactory(Binding binding, EndpointAddress endpoint) : base(binding, endpoint)
{ }
public CachedWebServiceChannelFactory(string endpointConfigurationName)
: base(endpointConfigurationName)
{ }
public override T CreateChannel(EndpointAddress address, Uri via)
{
var extendedProxy = new CachedWebServiceProxy<T>(typeof(T));
return (T)extendedProxy.GetTransparentProxy();
}
}

Ok, the basic issue was that I assumed that my code was wrapping the transparent proxy when in fact the transparent proxy is wrapping my class. I thought that what I could do is create an instance of the base proxy, call methods on this proxy and return the results.
Because my class is actually the base class for transparent proxy calling GetTransparentProxy just created a new instance of my class (which in turn created another new instance etc.)
I now realize that I should have been doing a similar kind of thing but within the ChannelFactory instead. This is a subclass so I can just wrap base.* methods in my own logic as I had hoped to do within the proxy class. What I now do is get an instance of the channel from a base method, I then pass it in to my RealProxy class and then use reflection to call the required method on the channel object.
Here is the code:
public class CachedWebServiceProxy<T> : RealProxy
{
private Type _typeOfProxy;
public object _channel;
public CachedWebServiceProxy(Type typeOfProxy, object channel)
: base(typeOfProxy)
{
_typeOfProxy = typeOfProxy;
_channel = channel;
}
public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
object result = null;
result = methodInfo.Invoke(_channel, methodCall.Args);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
}
public class CachedWebServiceChannelFactory<T> : ChannelFactory<T>
{
public CachedWebServiceChannelFactory(Binding binding, EndpointAddress endpoint)
: base(binding, endpoint)
{ }
public CachedWebServiceChannelFactory(string endpointConfigurationName)
: base(endpointConfigurationName)
{ }
public override T CreateChannel(EndpointAddress address, Uri via)
{
T innerChannel = base.CreateChannel(address, via);
var extendedProxy = new CachedWebServiceProxy<T>(typeof(T), innerChannel);
return (T)extendedProxy.GetTransparentProxy();
}
}
Joe

Related

Web API will not use ISerializable implementation

I thought I had jumped through the necessary hoops to get my JsonMediaTypeFormatter working with custom ISerializable implementations, complete with passing unit tests. But I'm unable to get it to work when I pass in values via Swagger UI.
My key questions are:
What am I doing wrong with my unit test causing it to serialize/deserialize different from what Web API is doing?
What do I need to change to get this working with Web API's serializing/deserialization and Swagger/Swashbuckle?
Class being serialized: (Notice that serializing and then deserializing drops off the time component and only keeps the date component. The helps for testing/observing purposes.)
public class Pet : ISerializable
{
public DateTime Dob { get; set; }
public Pet()
{
Dob = DateTime.Parse("1500-12-25 07:59:59");
}
public Pet(SerializationInfo info, StreamingContext context)
{
Dob = DateTime.Parse(info.GetString("Dob"));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Dob", Dob.Date.ToString());
}
}
Web API Method: (always returns null)
public class TestController : ApiController
{
[Route("~/api/Pet")]
public string Get([FromUri] Pet data)
{
return data.Dob.ToString();
}
}
Passing Unit Test: (and serialization helpers from MSDN docs)
[TestFixture]
public class SerializationTests
{
[Test]
public void PetTest()
{
var date = new DateTime(2017, 1, 20, 5, 0, 0);
var foo = new Pet { Dob = date };
var jsonFormatter = new JsonMediaTypeFormatter { SerializerSettings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { IgnoreSerializableInterface = false } } };
var serialized = SerializationHelpers.Serialize(jsonFormatter, foo);
Console.WriteLine(serialized);
var deserialized = SerializationHelpers.Deserialize<Pet>(jsonFormatter, serialized);
Assert.That(foo.Dob, Is.Not.EqualTo(date.Date));
Assert.That(deserialized.Dob, Is.EqualTo(date.Date));
}
}
public static class SerializationHelpers
{
public static string Serialize<T>(MediaTypeFormatter formatter, T value)
{
// Create a dummy HTTP Content.
Stream stream = new MemoryStream();
var content = new StreamContent(stream);
// Serialize the object.
formatter.WriteToStreamAsync(typeof(T), value, stream, content, null).Wait();
// Read the serialized string.
stream.Position = 0;
return content.ReadAsStringAsync().Result;
}
public static T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class
{
// Write the serialized string to a memory stream.
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
// Deserialize to an object of type T
return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.Formatters.Clear();
var jsonFormatter = new JsonMediaTypeFormatter { SerializerSettings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { IgnoreSerializableInterface = false } } };
config.Formatters.Add(jsonFormatter);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
A few other notes:
When I run the passing unit test, the Console.WriteLine output is:
{"Dob":"1/20/2017 12:00:00 AM"}
which is exactly what I want/expect.
My Swagger UI looks like this using the default Swashbuckle settings from Nuget. Note that value of the date is what is set in the default constructor, showing that my ISerializable implementation is ignored.
NOTE:
I have changed the question to remove all generics from the picture. This problem is fundamentally about ISerializable implementations now and not about Generics.
WebAPI api does not know how to deserialize this generic object. I see a similar question here in SO but did not personally try/test it. Hope it helps: Generic Web Api method
Rather than having a generic method, you can create a generic controller. So your code above will look something like below.
public abstract class MyClass{ }
public class PersonDto: MyClass{}
public class TestController<T> : ApiController where T: MyClass
{
public string Get([FromUri] T data)
{
...
}
}

GWT with Serialization

This is my client side code to get the string "get-image-data" through RPC calls and getting byte[] from the server.
CommandMessage msg = new CommandMessage(itemId, "get-image-data");
cmain.ivClient.execute(msg, new AsyncCallback<ResponseMessage>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(ResponseMessage result) {
if (result.result) {
result.data is byte[].
}
}
});
From the server side I got the length of the data is 241336.
But I could not get the value in onSuccess method. It is always goes to onFailure method.
And I got log on Apache:
com.google.gwt.user.client.rpc.SerializationException: Type '[B' was
not included in the set of types which can be serialized by this
SerializationPolicy or its Class object could not be loaded.
How can I do serialisation in GWT?
1) Create a pojo which implements Serializable interface
Let this pojo has all the data you want in the response of RPC service, in this case image-data
2) Pass this pojo in the response for your RPC service.
The below tutorial has enough information for creating RPC service
http://www.gwtproject.org/doc/latest/tutorial/RPC.html
The objects you transfer to and from the server has to implement IsSerializable.
All your custom Objects within the Object you are transferring also needs to implement IsSerializable.
Your objects cannot have final fields and needs an no argument constructor.
You need getters and setters.
A common serialize object in GWT:
public class MyClass implements IsSerializable {
private String txt;
private MyOtherClass myOtherClass; // Also implements IsSerializable
public MyClass() {
}
public String getTxt() {
return this.txt;
}
public void setTxt(String txt) {
return this.txt = txt;
}
public String getMyOtherClass() {
return this.myOtherClass;
}
public void setMyOtherClass(MyOtherClass myOtherClass) {
return this.myOtherClass = myOtherClass;
}
}

WCF avoiding too many endpoints for experts

I have a lot of businesses services already implemented, and I´m exposing them as services by WCF.
I don´t like the idea to have one endpoint to each service..... it could be a problem to maintain in the future as my repository grows.......
I´d like to know wcf´s experts opinions if the code below would be a good approach an them I can move ahead with this solution.
Business Service A:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
object AddA(object a);
[OperationContract]
object Update();
}
Business Service B:
[ServiceContract]
public interface IServiceB
{
[OperationContract]
object AddB(object b);
[OperationContract]
object Update();
}
Concrete implementation for Service A
public class ConcreteServiceA : IServiceA
{
public object AddA(object a)
{
Console.WriteLine("ConcreateServiceA::AddA");
return null;
}
public object Update()
{
Console.WriteLine("ConcreateServiceA::Update");
return null;
}
}
Concrete implementation for Service B
public class ConcreteServiceB : IServiceB
{
public object AddB(object b)
{
Console.WriteLine("ConcreateServiceB::AddB");
return null;
}
public object Update()
{
Console.WriteLine("ConcreateServiceB::Update");
return null;
}
}
My single service is partial to separate concerns to each service.
Note that it´s constructors depends on both business services above, will be injection using IoC
Partial for constructors
public partial class WCFService
{
IServiceA _a;
IServiceB _b;
public WCFService()
: this(new ConcreteServiceA(), new ConcreteServiceB())
{
}
public WCFService(IServiceA serviceA, IServiceB serviceB)
{
_a = serviceA;
_b = serviceB;
}
}
Partial class implementing only IServiveA
public partial class WCFService : IServiceA
{
object IServiceB.AddB(object b)
{
return _b.AddB(b);
}
object IServiceB.Update()
{
return _b.Update();
}
}
Partial class implementing only IServiceB
public partial class WCFService : IServiceB
{
object IServiceA.AddA(object a)
{
return _a.AddA(a);
}
object IServiceA.Update()
{
return _a.Update();
}
}
And in the client side, I using like that:
var endPoint = new EndpointAddress("http://localhost/teste");
ChannelFactory<IServiceA> _factoryA = new ChannelFactory<IServiceA>(new BasicHttpBinding(), endPoint);
IServiceA serviceA = _factoryA.CreateChannel();
serviceA.Update();
var netTcpEndPoint = new EndpointAddress("net.tcp://localhost:9000/teste");
ChannelFactory<IServiceB> _factoryB = new ChannelFactory<IServiceB>(new NetTcpBinding(), netTcpEndPoint);
IServiceB serviceB = _factoryB.CreateChannel();
serviceB.Update();
I really appreciate any opinion or other suggestions.
There's nothing wrong with multiple endpoints - it's part of the process. What is wrong, however, is duplicating functionality over multiple endpoints. How many "UpdateThis's" or "AddThat's" developers need? This can get out of control and makes for a maintenance headache. Just look at your constructor, it will grow and grow as you add new services and consolidate them into one service.
Think coarse-grained not fine-grained.
As an alternative, maybe you can try passing request objects as a parameter and returning response objects. This approach may streamline your code and help you avoid the maintenance issues you mention in your post and gives you a suggestion.
So, it looks something like this:
// Your service will return a very generic Response object
public interface IService
{
Response YourRequest(Request request);
}
// Your service implementation
public partial class WCFService : IService
{
Response IService.YourRequest(Request request)
{
//inspect the Request, do your work based on the values
//and return a response object
}
}
// Your request object
public class Request()
{
object YourClass{get;set;}
DoWhat Action{get;set;} //enum, constants, string etc.
int ID {get; set;}
}
// Your response object
public class Response()
{
bool Success {get; set;}
}
// Create Request object
var request = new Request(){YourClass = YourClassName , Action DoWhat.Update(), ID=1};
// Your service call
var endPoint = new EndpointAddress("http://localhost/teste");
ChannelFactory<IService> _factory = new ChannelFactory<IService>(new BasicHttpBinding(), endPoint);
IService service = _factory.CreateChannel();
var response = service.YourRequest(request);
So, now you've removed the fine-grained approach and replaced it with course-grained one. Let me know if you'd like more detail.

How to do Setup of mocks with Ninject's MockingKernel (moq)

I'm having a really hard time trying to figure how I can do .SetupXXX() calls on the underlying Mock<T> that has been generated inside the MockingKernel. Anyone who can shed some light on how it is supposed to work?
You need to call the GetMock<T> method on the MoqMockingKernel which will return the generated Mock<T> on which you can call your .SetupXXX()/VerifyXXX() methods.
Here is an example unit test which demonstrates the GetMock<T> usage:
[Test]
public void Test()
{
var mockingKernel = new MoqMockingKernel();
var serviceMock = mockingKernel.GetMock<IService>();
serviceMock.Setup(m => m.GetGreetings()).Returns("World");
var sut = mockingKernel.Get<MyClass>();
Assert.AreEqual("Hello World", sut.SayHello());
}
Where the involved types are the following:
public interface IService { string GetGreetings(); }
public class MyClass
{
private readonly IService service;
public MyClass(IService service) { this.service = service; }
public string SayHello()
{
return string.Format("Hello {0}", service.GetGreetings());
}
}
Note that you can access the generated Moq.MockRepository (if you prefer it over the SetupXXX methods) with the MoqMockingKernel.MockRepository property.

How do you mock the querystring in a WCF service?

I have a WCF service which has methods that depend on reading values (OData) from the http request's querystring. I'm trying to write unit tests which inject in mock values into the querystring, then when I call the method it would use these mock values rather than erroring due to the request context not being available.
I've tried using WCFMock (which is based on Moq) however I don't see a way to set or get the querystring from the WebOperationContext that it provides.
Any ideas?
I ended up using the IOC pattern to solve this, creating an IQueryStringHelper interface that is passed into the constructor of the service. If it isn't passed in then it'll default to use the "real" QueryStringHelper class. When running test cases, it'll use an overloaded service constructor to pass in the TestQueryStringHelper instance, which lets you set a mock value for the querystring.
Here is the querystring helper code.
public interface IQueryStringHelper {
string[] GetParameters();
}
public class QueryStringHelper : IQueryStringHelper {
public string[] GetParameters() {
var properties = OperationContext.Current.IncomingMessageProperties;
var property = properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
string queryString = property.QueryString;
return queryString.Split('&');
}
}
public class TestQueryStringHelper : IQueryStringHelper {
private string mockValue;
public TestQueryStringHelper(string value) {
mockValue = value;
}
public string[] GetParameters() {
return mockValue.Split('&');
}
}
And the service implementation:
public partial class RestService : IRestService {
private IAuthenticator _auth;
private IQueryStringHelper _queryStringHelper;
public RestService() : this(new Authenticator(), new QueryStringHelper()) {
}
public RestService(IAuthenticator auth, IQueryStringHelper queryStringHelper = null) {
_auth = auth;
if (queryStringHelper != null) {
_queryStringHelper = queryStringHelper;
}
}
}
And how to consume it from a test case:
string odata = String.Format("$filter=Id eq guid'{0}'", "myguid");
var service = new RestService(m_auth,new TestQueryStringHelper(odata));
var entities = service.ReadAllEntities();
Hopefully this helps someone else.