Code Monkey home page Code Monkey logo

wcfclientproxygenerator's People

Contributors

cmenzi avatar jantkacik avatar jweber avatar tohveliesine avatar varkkjuh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wcfclientproxygenerator's Issues

Version 2.2.4 caused System.InvalidOperationException

Here is the exception:

The synchronous OperationContract method 'GetCompaniesForLookup' in type 'DA.Services.CarPark.ServiceContracts.Common.v1.ILookupService' was matched with the task-based asynchronous OperationContract method 'GetCompaniesForLookupAsync' because they have the same operation name 'GetCompaniesForLookup'. When a synchronous OperationContract method is matched to a task-based asynchronous OperationContract method, any additional attributes must be declared on the synchronous OperationContract method. In this case, the task-based asynchronous OperationContract method 'GetCompaniesForLookupAsync' has one or more attributes of type 'FaultContractAttribute'. To fix it, remove the 'FaultContractAttribute' attribute or attributes from method 'GetCompaniesForLookupAsync'. Alternatively, changing the name of one of the methods will prevent matching.

Stack:

System.ServiceModel.Description.TypeLoader.SyncTaskOperationConsistencyVerifier.VerifyFaultContractAttribute()
System.ServiceModel.Description.TypeLoader.VerifyConsistency(OperationConsistencyVerifier verifier)
System.ServiceModel.Description.TypeLoader.CreateOperationDescription(ContractDescription contractDescription, MethodInfo methodInfo, MessageDirection direction, ContractReflectionInfo reflectionInfo, ContractDescription declaringContract)
System.ServiceModel.Description.TypeLoader.CreateOperationDescriptions(ContractDescription contractDescription, ContractReflectionInfo reflectionInfo, Type contractToGetMethodsFrom, ContractDescription declaringContract, MessageDirection direction)
System.ServiceModel.Description.TypeLoader.CreateContractDescription(ServiceContractAttribute contractAttr, Type contractType, Type serviceType, ContractReflectionInfo& reflectionInfo, Object serviceImplementation)
System.ServiceModel.Description.TypeLoader.LoadContractDescriptionHelper(Type contractType, Type serviceType, Object serviceImplementation)
System.ServiceModel.Description.ContractDescription.GetContract(Type contractType)
WcfClientProxyGenerator.ChannelFactoryProvider.GetClientEndpointConfiguration[TServiceInterface](Type serviceInterfaceType, String endpointConfigurationName)
WcfClientProxyGenerator.ChannelFactoryProvider.<>c__DisplayClass2_0`1.<GetChannelFactory>b__0()
WcfClientProxyGenerator.ChannelFactoryProvider.<>c__DisplayClass9_0`1.<GetChannelFactory>b__0(String _)
WcfClientProxyGenerator.Util.DictionaryExtensions.<>c__DisplayClass0_0`2.<GetOrAddSafe>b__0()
System.Lazy`1.CreateValue()

My sample solution at #19 (comment) would exhibit this behavior. For now, I'm reverting to 2.2.3.

Thanks!

WSHttpDualBinding

Hi,
first of all great work, thanks.

Can the proxy generator register a callbackhandler for dual channels?

Generated proxy class should be hookable (OnBeforeMethodCall, OnAfterMethodCall)

There should be a way to hook into when the client proxy is used to call a service method. Something like callbacks/events would be the way to go that would be called before and after a service method has been called.

Syntax could be something like this:

private void BeforeMethodGetsCalled(MethodInfo method) { /* .. */ }
private void AfterMethodGetsCalled(MethodInfo method) { /* .. */ }

// ...

IUsefulService service = WcfClientProxy.Create<IUsefulService>(c => {
    c.OnBeforeMethodCall += BeforeMethodGetsCalled;
    c.OnAfterMethodCall += AfterMethodGetsCalled;
});

Feature request: Adding Endpoint behaviors

There doesn't seem to be a way to add a custom IEndpointBehavior in the code (only through configuration file).

Endpoint behaviors in the WCF client side are required if you wish to hook a message inspector to for example look at the reply message (SOAP) header values.

If the IProxyConfigurator interface exposed ChannelFactory or its Endpoint field it would be possible to add custom behaviors. It could also be possible by adding a custom function or property for that. Which way do you think would be the best of these?

IUsefulService service = WcfClientProxy.Create<IUsefulService>(c => {
    // ...

    c.ChannelFactory.Endpoint.Behaviors.Add(new MyCustomEndpointBehavior());
    // or
    c.Endpoint.Behaviors.Add(new MyCustomEndpointBehavior());
    // or
    c.AddEndpointBehavior(new MyCustomEndpointBehavior());
});

I'd maybe go for exposing the whole ChannelFactory because it gives access to everything you'd ever need, but the users should be instructed that it may be null before calling c.SetEndpoint() or c.UseDefaultEndpoint(). Could there be problems caused by the fact that channel factories are cached?

I hope we can agree what to do here, but this would be a helpful feature exposing WCF extensibility for advanced use cases.

A standard way to have multiple proxies using Generics or something to have no redundant code

This is not really an issue but more of a standard.

I put up a question on SO. Here is the question:

using Silly.Services.CarPark.Logging;
using Silly.Services.CarPark.ServiceContracts.Common.v1;
using log4net;
using System.Linq;
using System.Threading.Tasks;
using WcfClientProxyGenerator;

namespace Silly.Services.CarPark.Client
{
    public class RequestManager
    {
        private static Log4NetLoggingAdapter systemLogger;
        private static IRequestService proxy = null;

        public RequestManager()
        {
            if (systemLogger == null)
            {
                LoggerSetup.Configure(Constants.ModuleNameForLogging);
                systemLogger = new Log4NetLoggingAdapter(LogManager.GetLogger(typeof(RequestManager)));
            }

            proxy = WcfClientProxy.Create<IRequestService>(c =>
            {
                c.SetEndpoint("BasicHttpBinding_IRequestService");

                c.OnCallBegin += (sender, args) => { };

                c.OnBeforeInvoke += (sender, args) =>
                {
                    systemLogger.Write(string.Format("{0}.{1} called with parameters: {2}", args.ServiceType.Name, args.InvokeInfo.MethodName, string.Join(", ", args.InvokeInfo.Parameters)), Core.EventSeverity.Verbose);
                };

                c.OnAfterInvoke += (sender, args) =>
                {
                    systemLogger.Write(string.Format("{0}.{1} returned value: {2}", args.ServiceType.Name, args.InvokeInfo.MethodName, args.InvokeInfo.ReturnValue), Core.EventSeverity.Verbose);
                };

                c.OnCallSuccess += (sender, args) =>
                {
                    systemLogger.Write(string.Format("{0}.{1} completed successfully", args.ServiceType.Name, args.InvokeInfo.MethodName));
                };

                c.OnException += (sender, args) =>
                {
                    systemLogger.Write(string.Format("Exception during service call to {0}.{1}: {2}", args.ServiceType.Name, args.InvokeInfo.MethodName, args.Exception.Message), args.Exception, Core.EventSeverity.Error);
                };
            });
        }
    }
}

If I have seven more services, I'll be writing six more proxies and i see redundant code. Can I use generics here? Aim is to keep redundant code to the minimum. I have removed the actual logging I'm doing and since I created the proxies, I have been changing the string and I have to do it at four different locations (four services so far)

NullReferenceException for null result

Hi.
Recently I upgraded WcfClientProxygenerator from version 1.2.5 to 2.1.0.
Now, when I try to call a WCF service method that returns null, I get NullReferenceException from client proxy:

   at WcfClientProxyGenerator.RetryingWcfActionInvoker`1.HandleOnAfterInvoke(Int32 retryCounter, Object response, InvokeInfo invokeInfo)
   at WcfClientProxyGenerator.RetryingWcfActionInvoker`1.Invoke[TResponse](Func`2 method, InvokeInfo invokeInfo)
   at WcfClientProxyGenerator.DynamicProxy.ICaseService.GetTotalItemCount(FilterModel filter)
   at TestWcfClient.Program.Main(String[] args) in c:\Users\j.leszczynski\Documents\Visual Studio 2013\Projects\TestWcfClient\TestWcfClient\Program.cs:line 17
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Service method

public string GeString()
    {
      return null;
    }

Client method

static void Main(string[] args)
    {
      var client = WcfClientProxyGenerator.WcfClientProxy.Create<ICaseService>();

      var result = client.GeString();
    }

Async failing either ways

I'm trying to call the Async version of the APIs I have but regardless of the the way I cook a proxy proxyLookupAsync = (WcfClientProxy.CreateAsyncProxy<ILookupService> or proxyLookup = WcfClientProxy.Create<ILookupService>), I get this exception once I call an API:

System.NotSupportedException:
Method GetCompaniesAsync is not supported on this proxy, this can happen if the method is not marked with OperationContractAttribute or if the interface type is not marked with ServiceContractAttribute.

Here is my contract:

using DA.Services.CarPark.ServiceCommon;
using System.Collections.Generic;
using System.ServiceModel;

namespace DA.Services.CarPark.ServiceContracts.Common.v1
{

    [ServiceContract(Namespace = Constants.ServiceNamespace)]
    public interface ILookupService
    {

        [OperationContract]
        [FaultContract(typeof(CarParkFault))]
        IList<BDO.Company> GetCompanies();

    }
}

Here is CarParkFault

using System.Runtime.Serialization;

namespace DA.Services.CarPark.ServiceCommon
{
    [DataContract]
    public class CarParkFault
    {
        [DataMember]
        public string FaultMessage;

        public CarParkFault(string ErrMessage)
        {
            FaultMessage = ErrMessage;
        }
    }
}

And Constants.ServiceNamespace is:

public const string ServiceNamespace = "http://www.myairports.ae/internal/services/";

What am I missing here?

Any chance for a .net 4 assembly?

My project is using .net 4 and sadly at this point I cannot upgrade to 4.5
Is there any chance of getting this compiled against .net 4?

Version 2.2.5 caused System.InvalidOperationException

Hi. I'm using version 2.2.5 and I'm getting the same exception (as #22) on an interface that only has non-async operations on it. I've tried to revert to 2.2.3 but still no luck. I'm not sure if I can post the contract as is but I'll try to rename everything as much as I can without giving away exactly what it is or what it is used for in my current line of business work.

    [ServiceContract(
        Namespace = Constants.NAMESPACE,
        Name = "SomeVendorServices")]
    public interface ISomeVendorServices
    {
        [OperationContract]
        Operation1Response GetOperation1(Operation1Request request);

        [OperationContract]
        Operation2Response RequestOperation2(Operation2Request request);

        [OperationContract]
        Operation3Response RequestOperation3(Operation3Request request);

        [OperationContract]
        Operation4Response RequestOperation4(Operation4Request request);

        [OperationContract]
        Operation5Response GetOperation5(Operation5Request request);
    }

    static class Constants
    {
        public const string NAMESPACE = "SomeDomain.Contracts";
    }

    WcfClientProxy.Create<ISomeVendorServices>(d => d.UseDefaultEndpoint())

I've created this even in a clean console app and it still failed.

I'm using Visual Studio 2015 with .NET 4.5.2

Custom attribute on the service contract does not work.

Hi jweber,

Greate library!

but I found it seems the custom attribute on the service contract won't work after using the library, because the interface generated won't inherit the attributes on the original interface.

Thanks,

Doesn't seem to work with OperationContract with out parameter

WcfClientProxy.Create() will fail when generating the service call wrapper type on an operation with out parameter. (e.g.: int Test(MarshalledObject mo, out byte[] timeStamp);)

Run-time type generation is something I don't know much about, but I'll try to investigate the issue though.

Btw, great initiative!

Got a COMException with the following message:
"Field of ByRef type. (Exception from HRESULT: 0x801312E4)"

Here's the callstack:
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at WcfClientProxyGenerator.DynamicProxyTypeGenerator1.GenerateServiceCallWrapperType(MethodInfo methodInfo, Type[] parameterTypes, Type& generatedType) in WcfClientProxyGenerator\DynamicProxyTypeGenerator.cs:line 263 at WcfClientProxyGenerator.DynamicProxyTypeGenerator1.GenerateServiceProxyMethod(MethodInfo methodInfo, TypeBuilder typeBuilder) in WcfClientProxyGenerator\DynamicProxyTypeGenerator.cs:line 115
at WcfClientProxyGenerator.DynamicProxyTypeGenerator1.GenerateType[TActionInvokerProvider]() in WcfClientProxyGenerator\DynamicProxyTypeGenerator.cs:line 70 at WcfClientProxyGenerator.WcfClientProxy.<GetProxyType>b__3[TServiceInterface,TActionInvokerProvider](Type _) in WcfClientProxyGenerator\WcfClientProxy.cs:line 80 at WcfClientProxyGenerator.Util.DictionaryExtensions.<>c__DisplayClass12.b__0() in WcfClientProxyGenerator\Util\DictionaryExtensions.cs:line 14
at System.Lazy1.CreateValue() at System.Lazy1.LazyInitValue()
at System.Lazy1.get_Value() at WcfClientProxyGenerator.Util.DictionaryExtensions.GetOrAddSafe[TKey,TValue](ConcurrentDictionary2 dictionary, TKey key, Func2 valueFactory) in WcfClientProxyGenerator\Util\DictionaryExtensions.cs:line 15 at WcfClientProxyGenerator.WcfClientProxy.GetProxyType[TServiceInterface,TActionInvokerProvider]() in WcfClientProxyGenerator\WcfClientProxy.cs:line 78 at WcfClientProxyGenerator.WcfClientProxy.CreateProxy[TServiceInterface,TActionInvokerProvider](Object[] arguments) in WcfClientProxyGenerator\WcfClientProxy.cs:line 70 at WcfClientProxyGenerator.WcfClientProxy.Create[TServiceInterface](Action1 configurator) in WcfClientProxyGenerator\WcfClientProxy.cs:line 50

Feature request: OnException handler

In version 1.2.4 we got OnBeforeInvoke and OnAfterInvoke events, which may be used to execute user code on calling of the service and successful return.

To execute code on exceptions, one may, of course, use a try { } catch { } block, but it does not answer the need for things like tracing libraries where you need to have it one layer above the application code.

There is RetryOnException which can be used to execute code on a specific type exception, but cannot be used as a "catch-all" as the types are matched exactly. Also as the name implies, it is meant for for quite different purpose.

Introducing the OnException event, it should behave similar to OnBeforeInvoke, firing on every exception received on the call (even retries), and should allow access to the original exception object.

Channel gets closed after every call to Invoke

Currently, every call of RetryingWcfActionInvoker.Invoke constructs its own provider instance and disposes it afterwards. This causes a problem with long running duplex connections because the channel gets closed.

In 2.1.2 I used the following patched version that caches its provider between calls and only replaces it when something goes wrong.

        private TServiceInterface provider;

        /// <summary>
        /// This function is called when a proxy's method is called that should return something.
        /// </summary>
        /// <param name="method">Method implementing the service call using WCF</param>
        /// <param name="invokeInfo"></param>
        public TResponse Invoke<TResponse>(Func<TServiceInterface, TResponse> method, InvokeInfo invokeInfo = null)
        {
            provider = this.RefreshProvider(provider, 0, invokeInfo);
            TResponse lastResponse = default(TResponse);
            IDelayPolicy delayPolicy = this.DelayPolicyFactory();

            var sw = Stopwatch.StartNew();

            this.HandleOnCallBegin(invokeInfo);

            Exception mostRecentException = null;
            for (int i = 0; i < this.RetryCount + 1; i++)
            {
                try
                {
                    this.HandleOnBeforeInvoke(i, invokeInfo);

                    // make the service call
                    TResponse response = method(provider);

                    this.HandleOnAfterInvoke(i, response, invokeInfo);

                    if (this.ResponseInRetryable(response))
                    {
                        lastResponse = response;
                        provider = this.Delay(i, delayPolicy, provider, invokeInfo);
                        continue;
                    }

                    sw.Stop();

                    response = this.ExecuteResponseHandlers(response);

                    this.HandleOnCallSuccess(sw.Elapsed, response, (i + 1), invokeInfo);

                    return response;
                }
                catch (Exception ex)
                {
                    this.HandleOnException(ex, i, invokeInfo);

                    if (this.ExceptionIsRetryable(ex))
                    {
                        mostRecentException = ex;
                        provider = this.Delay(i, delayPolicy, provider, invokeInfo);
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            if (mostRecentException != null)
            {
                if (RetryCount == 0)
                    throw mostRecentException;

                var exception = this.RetryFailureExceptionFactory(this.RetryCount, mostRecentException, invokeInfo);
                throw exception;
            }

            return lastResponse;
        }

I've used this in production for a couple of months and it works just fine. Unfortunately I can't port it to 2.2.0 because our company doesn't have access to VS2015 yet. So consider this an informal pull request.

P.S.: the same probably applies to InvokeAsync.

How to set OutgoingMessageProperties

I am trying to replace a custom WcfClientProxy with WcfClientProxyGenerator and I am not sure how to handle adding outgoing message properties.

Current implementation looks something like this.

using (new OperationContextScope(proxy))
{
// Adding HTTP header OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = AuthorizationHeaderFactory.Create();

How can this be accomplised with WcfClientProxyGenerator? If not supported, do you have a suggestion on how to extend it to support it?

.Net Framework 4.8

For reasons I cannot explain (2 days of continuous debugging), when I upgraded two of my running project to .Net 4.8, I started to get he message with Action 'http://carpark.company.com/services/internal/ILookupService/GetRequestTypes' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

Reverting back to 4.7.2 resolves this.

Could you find time to validate this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.