"Value of ContainerControlledLifetimeManager can only be set once" when using an open-generic singleton registration - unity-container

I'm using the Unity.Container NuGet package 5.11 and I want to register an open-generic type such that each concrete type is a singleton.
Background: I'm working in an old-school ASP.NET WebForms application and I've made a crude reimplementation of Microsoft.Extensions.Logging like so:
// `ILogger` is implemented elsewhere. Specifically I wrote an implementation using Serilog.
public interface ILogger
{
void Log( LogLevel level, String messageTemplate, params Object[] args );
}
// Unlike `ILogger`, this `ILogger<TSourceContext>` is not implemented by the code elsewhere (that uses Serilog, described above).
// Instead, it's only implemented by the internal class below:
public interface ILogger<TSourceContext> : ILogger
{
}
internal class LoggerWithSourceContext<TSourceContext> : ILogger<TSourceContext>
{
private readonly ILogger realLogger;
internal LoggerWithSourceContext( ILoggerFactory factory )
{
if( factory == null ) throw new ArgumentNullException(nameof(factory));
this.realLogger = factory.CreateLogger( sourceContext: typeof(TSourceContext).FullName );
}
public void Log( LogLevel level, String messageTemplate, params Object[] args )
{
this.realLogger.Log( level, messageTemplate, args );
}
}
// This is implemented elsewhere in my Serilog code.
public interface ILoggerFactory
{
ILogger CreateLogger( String sourceContext );
}
This is registered in my root Unity container like so:
IUnityContainer rootContainer = ...
rootContainer
.RegisterSingleton<ILoggerFactory,MySerilogLoggerFactory>()
.RegisterSingleton( from: typeof(ILogger<>), to: typeof(LoggerWithSourceContext<>);
When this is used, the first time an ILogger<T> is resolved it works fine - however the second time an ILogger<T> is resolved it fails with this error:
InvalidOperationException
ContainerControlledLifetimeManager can only be set once
I was able to work-around it by changing the registration from a Singleton to a Transient registration using RegisterType, but I'd like it to use a Singleton registration to mitigate the risks of a memory or resource leak:
IUnityContainer rootContainer = ...
rootContainer
.RegisterSingleton<ILoggerFactory,MySerilogLoggerFactory>()
.RegisterType( from: typeof(ILogger<>), to: typeof(LoggerWithSourceContext<>);
Full stack trace:
ContainerControlledLifetimeManager can only be set once
-2146233079
System.InvalidOperationException
at Unity.Lifetime.ContainerControlledLifetimeManager.<>c.<SetValue>b__7_0(Object o, ILifetimeContainer c) in C:\projects\unity\Abstractions\src\Lifetime\Managers\ContainerControlledLifetimeManager.cs:line 70
at Unity.Lifetime.ContainerControlledLifetimeManager.SetValue(Object newValue, ILifetimeContainer container) in C:\projects\unity\Abstractions\src\Lifetime\Managers\ContainerControlledLifetimeManager.cs:line 70
at Unity.Strategies.LifetimeStrategy.PostBuildUp(BuilderContext& context) in C:\projects\unity\Container\src\Strategies\LifetimeStrategy.cs:line 86
at Unity.UnityContainer.<>c.<.ctor>b__41_3(BuilderStrategy[] chain, BuilderContext& context) in C:\projects\unity\Container\src\UnityContainer.Resolution.cs:line 431
at Unity.Builder.BuilderContext.Resolve(Type type, String name, InternalRegistration registration) in C:\projects\unity\Container\src\Builder\Context\BuilderContext.cs:line 177
at Unity.Builder.BuilderContext.Resolve(Type type, String name) in C:\projects\unity\Container\src\Builder\Context\BuilderContext.cs:line 67
at Unity.Builder.BuilderContext.Resolve(ParameterInfo parameter, Object value) in C:\projects\unity\Container\src\Builder\Context\BuilderContext.cs:line 217
at Unity.Processors.ConstructorProcessor.<>c__DisplayClass16_0.<GetResolverDelegate>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Constructor\ConstructorResolution.cs:line 77
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Abstracts\MemberProcessor.cs:line 162
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Abstracts\MemberProcessor.cs:line 162
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c) in C:\projects\unity\Container\src\Processors\Abstracts\MemberProcessor.cs:line 162
at Unity.Strategies.BuildPlanStrategy.PreBuildUp(BuilderContext& context) in C:\projects\unity\Container\src\Strategies\BuildPlanStrategy.cs:line 88
at Unity.UnityContainer.<>c.<.ctor>b__41_2(BuilderContext& context) in C:\projects\unity\Container\src\UnityContainer.Resolution.cs:line 363
at Unity.UnityContainer.Unity.IUnityContainer.Resolve(Type type, String name, ResolverOverride[] overrides) in C:\projects\unity\Container\src\UnityContainer.IUnityContainer.cs:line 244

Now in latest unity version 5.11.7 this problem fixed

Related

ASP.NET Core Dependency Injection inside Startup.Configure

I am using the Cookie Middleware to authenticate the user. I have been following this official tutorial.
Inside my Startup class, an excerpt from my Configure method looks like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// ...
// Cookie-based Authentication
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Events = new CustomCookieAuthenticationEvents(app),
});
// ...
}
The CustomCookieAuthenticationEvents class is defined as follows:
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
private IApplicationBuilder _app;
private IMyService _myService = null;
private IMyService MyService
{
get
{
if(_myService != null)
{
return _myService;
} else
{
return _myService = (IMyService) _app.ApplicationServices.GetService(typeof(IMyService));
}
}
}
public CustomCookieAuthenticationEvents(IApplicationBuilder app)
{
_app = app;
}
public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
string sessionToken = context.Principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Sid)?.Value;
LogonSession response = null;
var response = await MyService.CheckSession(sessionToken);
if (response == null)
{
context.RejectPrincipal();
await context.HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
}
}
Since the dependency injection is not available at Startup.Configure (the services are not even registered at that point), I made a bit of a workaround:
Pass IApplicationBuilder service to the CustomCookieAuthenticationEvents class
Fetch IMyService upon first request inside a read-only property (singleton pattern)
tl;dr
My solution works, but it's ugly. There is no dependency injection involved, as it is not possible at that time.
The essence of the problem is that I must instantiate CustomCookieAuthenticationEvents. As far as I have read the source code, there is no way around this, because the UseCookieAuthentication throws an exception if I omit the options parameter.
Any suggestion how can one make my current solution nicer?
Startup.ConfigureServices() is called before Startup.Configure() (see https://learn.microsoft.com/en-us/aspnet/core/fundamentals/startup for more information). So Dependency Injection is available at that time ;)
As a consequence, you can resolve your dependence in your configure method like this:
app.ApplicationServices.GetRequiredService<CustomCookieAuthenticationEvents>()
You should be really careful when you resolve services inside middleware. Your current approach (and the one suggested by #arnaudauroux) can result in difficulties when you use/need/require scoped services (i.e. usage of DbContext).
Resolving via app.ApplicationServices results in static (singleton) services, when the service is registered as scoped (transient are resolved per call, so they are not affected). It would be better to resolve your service during the request from HttpContext inside ValidatePrincipal method.
public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
string sessionToken = context.Principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Sid)?.Value;
LogonSession response = null;
var myService = context.HttpContext.RequestServices.GetService<IMyService >();
var response = await myService.CheckSession(sessionToken);
if (response == null)
{
context.RejectPrincipal();
await context.HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
}
With this approach you don't need to pass any dependencies inside your CustomCookieAuthenticationEvents class at all. HttpContext.RequiredServices is made specifically for such classes (any other can be solved via constructor injection, but not middleware and http context related pipeline, as there is no other otherway to correctly resolve scoped services in middlewares - Middleware instance is static and only instantiated once per request)
This way you won't have lifetime issues with your scoped services.
When you resolve transient services, they will be disposed at the end of request. Whereas transient services resolved via app.ApplicationServices will be resolved at some point in future after the request is finished and when garbage collection triggers (means: your resources will be freed at the earliest possible moment, which is when the request ends).

Mock logger giving me error for ASP.NET Core

I was trying to verify whether my log warning message is written via NUnit mocking. I am getting this error message :
An exception of type 'System.NotSupportedException' occurred in Moq.dll but was not handled in user code
Additional information: Invalid verify on a non-virtual (overridable in VB) member: m => m.LogWarning(String.Format("comments not found for part number :{0}", (Object)0), new[] { "111" })
code:
mockLogger.Verify(m => m.LogWarning($"comments not found for part number :{0}", "111"), Times.Exactly(1));
This is happening because NUnit mocking framework does not support extension methods. A few people on stack overflow have suggested to use Log method instead of level wise methods.
What am I missing?
Firstly, you don't need the $ at the start of the string. That's for string interpolation. The LogWarning message is doing a string.format, hence the {0}
Mock frameworks cannot directly mock static methods. The problem in your case is the LogWarning method - that is the static (extension) method.
The simplest way of overcoming this issue is by using a wrapper class. Here's how I got it, in your case.
Firstly I created an interface
public interface IMyLogWarning
{
void LogWarning(string msg, params object[] args);
}
Then I created a class which implements that interface
public class MyLogWarning<T> : IMyLogWarning where T : class
{
private readonly ILogger _logger;
public MyLogWarning(ILogger<T> logger)
{
// Using constructor for DI
_logger = logger;
}
public void LogWarning(string msg, params object[] args)
{
_logger.LogWarning(msg, args);
}
}
The reason for these two is that I'll use these in my code as well as the unit test.
The constructor in the class is setup so it can be populated using dependency injection, something like this in your ConfigureServices method. Feel free to change this; was a quick stab at it on my part.
services.AddTransient<IMyLogWarning, MyLogWarning<MyViewModel>>();
You can then create a unit test that's roughly like this
[Test]
public void LoggingTest_LogAMessage_ConfirmedLogWasRun()
{
// TODO - add the rest of your test code
// Arrange
var warningMsg = "comments not found for part number :{0}";
var partNumber = "111";
var mockLogger = new Mock<IMyLogWarning>();
// Act
mockLogger.Object.LogWarning(warningMsg, partNumber);
// Assert
mockLogger.Verify(m => m.LogWarning(warningMsg, partNumber), Times.Exactly(1));
}

Hosting SignalR with self host in Windows Service

I am new by signalR and Owin and need help.
I wrote all my signalR code in a library [My hub will be self hosted]. Then i referenced that lib from a windows service application, installed the Package "Microsoft.Owin.Host.HttpListener" in the windows service application and tried to execute it.
I am getting that wired exception:
Sequence contains no matching element
I tested my Library in a winForm application and it worked correctly.
I have no idea why i am getting that.
Update: Code example:
In My Library "myLib"
private IDisposable host;
private bool Start()
{
try
{
string url = "http://localhost:5000/";
host = SelfHost.Host(url);
}
catch (Exception ex)
{
log.WriteLine("************HOSTING FAILED ********************************* ex.ToString():"+ ex.ToString()+
" Ex.StackTrace: "+ex.StackTrace +" EX.Message: " + ex.Message + "***************");
}
}
private bool Stop()
{
if (host != null)
{
host.Dispose();
}
}
My SelfHost class:
class SelfHost
{
public static IDisposable Host(string url)
{
return WebApplication.Start<SelfHost>(url);
}
public void Configuration(IAppBuilder app)
{
// Turn cross domain on
var config = new HubConfiguration { EnableCrossDomain = true };
// This will map out to http://localhost:8080/signalr by default
app.MapHubs(config);
}
}
after creating an object from this lib in my windows service application:
myLib l = new myLib();
i implements the OnStart() of the windows Service which starts a thread that calls the Start()-function from myLib:
protected override void OnStart(string[] args)
{
Thread t = new Thread(new ThreadStart(this.StartServiceThread));
t.CurrentCulture = new System.Globalization.CultureInfo("en-US");
t.Start();
}
private void StartServiceThread()
{
l.Start();
}
Output [Ex-Details]
************HOSTING FAILED *********************************
ex.ToString():
System.InvalidOperationException: Sequence contains no matching element
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
at Microsoft.Owin.Hosting.ServerFactory.DefaultServerFactoryLoader.Load(String serverName)
at Microsoft.Owin.Hosting.KatanaEngine.ResolveServerFactory(StartContext context)
at Microsoft.Owin.Hosting.KatanaEngine.Start(StartContext context)
at Microsoft.Owin.Hosting.Starter.DirectHostingStarter.Start(StartOptions options)
at Microsoft.Owin.Hosting.KatanaStarter.Start(StartOptions options)
at Microsoft.Owin.Hosting.WebApplication.Start[TStartup](IServiceProvider services, StartOptions options)
at Microsoft.Owin.Hosting.WebApplication.Start[TStartup](StartOptions options)
at Microsoft.Owin.Hosting.WebApplication.Start[TStartup](String url)
at SelfHost.Host(String url) in SelfHost.cs:line 29
at myLib.Start() in myLib.cs:line 381
Ex.StackTrace:
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
at Microsoft.Owin.Hosting.ServerFactory.DefaultServerFactoryLoader.Load(String serverName)
at Microsoft.Owin.Hosting.KatanaEngine.ResolveServerFactory(StartContext context)
at Microsoft.Owin.Hosting.KatanaEngine.Start(StartContext context)
at Microsoft.Owin.Hosting.Starter.DirectHostingStarter.Start(StartOptions options)
at Microsoft.Owin.Hosting.KatanaStarter.Start(StartOptions options)
at Microsoft.Owin.Hosting.WebApplication.Start[TStartup](IServiceProvider services, StartOptions options)
at Microsoft.Owin.Hosting.WebApplication.Start[TStartup](StartOptions options)
at Microsoft.Owin.Hosting.WebApplication.Start[TStartup](String url)
at SelfHost.Host(String url) in SelfHost.cs:line 29
at myLib.Start() in myLib.cs:line 381
EX.Message: Sequence contains no matching element***************
Thanks in Advance!
I figured out what the problem was. I wrote myLib Code two months ago and was testing it using the winForms Application that i also wrote 2 months ago.
But yesterday i installed the new Owin Packages in my windows service application and tried to use the same library that i wrote before and so i got the error.
The problem is that the NuGetPackage in myLib (old version of Owin.Hosting) is not compatible with the new package version which is released 12 days ago . The new changes do not support WebApplication (from old version). It is called now WebApp.

Using simplemembership within ninject repository - via API & standard controller

I am building a fairly small sized mvc4 application. I want to use the simple membership provided as in time I can it being useful for the social stuff.
I want to be able to take advantage of the webapi within the project as I am building an ios application and would like for it to be able to use the same registration/account details. I have added an API area to the site.
I am using ninject for my injection so I have created a repository and have taken the default membership registration component and put it into this.
My Account controller and the apicontroller use the same repository.
public RegisterModel RegisterLocalUser(RegisterModel model)
{
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password,
new
{
Mobile = model.Mobile,
FirstName = model.FirstName,
LastName = model.LastName,
Email = model.Email,
});
Creating a user using the site works fine however when I try to use the api via fiddler to create a user I run into an issue of
{"Message":"An error has occurred.","ExceptionMessage":"You must call the \"WebSecurity.InitializeDatabaseConnection\" method before you call any other method of the \"WebSecurity\" class. This call should be placed in an _AppStart.cshtml file in the root of your site.","ExceptionType":"System.InvalidOperationException","StackTrace":" at WebMatrix.WebData.SimpleMembershipProvider.VerifyInitialized()\r\n at WebMatrix.WebData.WebSecurity.VerifyProvider()\r\n at WebMatrix.WebData.WebSecurity.CreateUserAndAccount(String userName, String password, Object propertyValues, Boolean requireConfirmationToken)\r\n at MySite.Web.Repository.AccountRepository.RegisterLocalUser(RegisterModel model) in c:\#Projects\Site\Site\Site.Consumer.Web\Repository\AccountRepository.cs:line 28\r\n at MySite.Web.Areas.API.Controllers.AccountController.RegisterLocal(RegisterModel data) in c:\#Projects\Site\Site\Site.Consumer.Web\Areas\API\Controllers\AccountController.cs:line 26\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c_DisplayClass13.b_c(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c_DisplayClass5.b_4()\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)"}
Adding a breakpoint within the repository the CreateUserAndAccount is never completed.
I have a custom DependancyResolver needed to allow the api and mvc stuff to work
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Has someone else been able to find a work around to get these components working together?
Thank you
Your error dump suggests you are not using the InitializeSimpleMembershipAttribute for your AccountController.
Either decorate your new account controller with InitializeSimpleMembershipAttribute or move that Websecurity.InitializeDatabaseConnection() to your Global.asax startup code.
Of course, this ignores the dependency issue and I don't have a good answer for that as I don't bother injecting WebSecurity.
WebSecurity is a static class
You'd only need to call InitializeDatabaseConnection once at startup. With the attribute usage it's called each time the controller is accessed.
Which means you must inject an initialized WebSecurity into your repository.

WCF Error in deserializing body of request message for operation

I have a asp.net client web application and a WCF web service which was developed from schema xsd. When calling the service i get an error in deserializing body of request. I tried updating service reference but that did not help.
This is my code:
OSEOP.HMA_OrderingBindingClient client = new OSEOP.HMA_OrderingBindingClient();
OSEOP.GetCapabilitiesRequest request = new OSEOP.GetCapabilitiesRequest();
request.GetCapabilities = new OSEOP.GetCapabilities();
request.GetCapabilities.service = "OS";
string[] arrAcceptedVersions = { "1.0.0", "2.0.0" };
request.GetCapabilities.AcceptVersions = arrAcceptedVersions;
OSEOP.Capabilities capabilities = client.GetCapabilities(request.GetCapabilities);
txtGetCapabilitiesResponse.Text = capabilities.Contents.ToString();
client.Close();
and this is the error:
System.ServiceModel.FaultException`1 was unhandled by user code
Message=Error in deserializing body of request message for operation 'GetCapabilities'.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at OSEOP.HMA_OrderingBinding.GetCapabilities(GetCapabilitiesRequest request)
at OSEOP.HMA_OrderingBindingClient.OSEOP.HMA_OrderingBinding.GetCapabilities(GetCapabilitiesRequest request) in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\oseop_testclient\023fa9f5\ea876945\App_WebReferences.k9c5tqe1.0.cs:line 44135
at OSEOP.HMA_OrderingBindingClient.GetCapabilities(GetCapabilities GetCapabilities1) in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\oseop_testclient\023fa9f5\ea876945\App_WebReferences.k9c5tqe1.0.cs:line 44141
at _Default.cmdGetCapabilities_Click(Object sender, EventArgs e) in d:\Documents\DEV\SARPilot\SVN_repository\Services\OrderingServices\TestClient\Default.aspx.cs:line 30
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
as you can see, the error happens at the client and never gets sent out to the WCF service. For this reason i'm not getting anything in my MessageLogging. That's why i thought it would have something to do with the service reference.
Can anyone help?
EDIT #1:
What i don't understand is the GetCapabilities takes a GetCapabilitiesRequest parameter but when i'm implementing the client, my intellisense asks for a OSEOP.GetCapabilities object.
OSEOP is what i named the web reference.
public class OrderingService : HMA_OrderingBinding
{
public GetCapabilitiesResponse GetCapabilities(GetCapabilitiesRequest request)
{
throw new NotImplementedException();
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.opengis.net/oseop/1.0", ConfigurationName = "HMA_OrderingBinding")]
public interface HMA_OrderingBinding
{
[OperationContract]
[XmlSerializerFormatAttribute]
GetCapabilitiesResponse GetCapabilities(GetCapabilitiesRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.opengis.net/oseop/1.0")]
public partial class Capabilities : CapabilitiesBaseType
{
private OrderingServiceContentsType contentsField;
private NotificationProducerMetadataPropertyType notificationsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public OrderingServiceContentsType Contents
{
get
{
return this.contentsField;
}
set
{
this.contentsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public NotificationProducerMetadataPropertyType Notifications
{
get
{
return this.notificationsField;
}
set
{
this.notificationsField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
public partial class GetCapabilitiesRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.opengis.net/oseop/1.0", Order = 0)]
public GetCapabilities GetCapabilities;
public GetCapabilitiesRequest()
{
}
public GetCapabilitiesRequest(GetCapabilities GetCapabilities)
{
this.GetCapabilities = GetCapabilities;
}
}
EDIT #2 #Marc:
Marc, your answer was very helpful. But you see how the server side is something like this:
GetCapabilitiesResponse GetCapabilities(GetCapabilitiesRequest request)
Yet my intellisense thinks it's something like this:
Capabilities GetCapabilities(GetCapabilities GetCapabilities1)
And I've found a snippet of code within the IOrder.cs file (47,256 lines of code generated from schema) that I'm sure is causing the problem but I tried commenting out the trouble function, updating service reference, and my intellisense still wants GetCapabilities GetCapabilities1
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class HMA_OrderingBindingClient : System.ServiceModel.ClientBase<HMA_OrderingBinding>, HMA_OrderingBinding
{
public HMA_OrderingBindingClient()
{
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
GetCapabilitiesResponse HMA_OrderingBinding.GetCapabilities(GetCapabilitiesRequest request)
{
return base.Channel.GetCapabilities(request);
}
public Capabilities GetCapabilities(GetCapabilities GetCapabilities1)
{
GetCapabilitiesRequest inValue = new GetCapabilitiesRequest();
inValue.GetCapabilities = GetCapabilities1;
GetCapabilitiesResponse retVal = ((HMA_OrderingBinding)(this)).GetCapabilities(inValue);
return retVal.Capabilities;
}
}
Two questions:
Why do you create a GetCapabilitiesRequest object which contains a subobject GetCapabilities, and then in your method call, you only use the contained suboject GetCapabilities??
So why not just create the GetCapabilities in the first place and forget about the wrapping object??
Also, can you please show us the GetCapabilitiesRequest and GetCapabilities and the return class Capabilities, too? If you have a deserialization error, most likely something with those classes isn't right...
Update: thanks for the update to your question....
hmm... can't seem to find anything obviously wrong at first glance....
About your question:
What I don't understand is the
GetCapabilities takes a
GetCapabilitiesRequest parameter but
when I'm implementing the client, my
intellisense asks for a
OSEOP.GetCapabilities object.
Yes, that's clear - your service-side uses its set of classes - GetCapabilitiesRequest and so forth.
When you do an Add Service Reference in Visual Studio, what VS does is
interrogate the server to find out about the service - what methods it has and what parameters it needs
it creates a set of copies of your classes for the client-side proxy - in that namespace that you define on the Add Service Reference dialog box. Those are classes that look exactly the same as your server side classes - but they are not the same classes - they just serialize to XML (and deserialize from XML) the same way as those on the server. That's why your client-side proxy has different classes in a different namespace. That's standard WCF behavior - nothing to be alarmed about...
Update no. 2: Carlos, the schema you sent me seems to be incomplete or has errors. Try to use OGC project on CodePlex as a base and build in your code manually or wait until the schema gets ‘officially’ published.

Resources