Blazor 0.6.0 "wipes" Flurl-compatibility? - flurl

After updating Blazor from 0.5.1 (with working Flurl) to 0.6.0, calls via flurl throw an exception:
WASM: [Flurl.Http.FlurlHttpException] Call failed. Cannot invoke method
because it was wiped. See stack trace for details.
The project creates a HttpClientFactory which gets Blazor's HttpClient for being used by Flurl:
Create FlurlClient with Blazor's HttpClient (http) using HttpClientFactoryForBlazor:
IFlurlClient c = new FlurlClient() { Settings = new Flurl.Http.Configuration.ClientFlurlHttpSettings { HttpClientFactory = new HttpClientFactoryForBlazor(http) }};
Use the FlurlClient (c) for example by via Flurl's extensionmethod "IFlurlRequest.WithClient(c);"
private class HttpClientFactoryForBlazor : Flurl.Http.Configuration.IHttpClientFactory
{
private readonly HttpClient httpClient;
public HttpClientFactoryForBlazor(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public virtual HttpClient CreateHttpClient(HttpMessageHandler handler)
{
return this.httpClient;
}
}
So, it seems like this approach does no longer work.
Does anybody know how to make Flurl with Blazor 0.6.0 work?
Call-Stack is:
WASM: [Flurl.Http.FlurlHttpException] Call failed. Cannot invoke method because it was wiped. See stack trace for details. GET http://srv01.servicegrid.eu:4455/API/Status?forceLoadDbs=False blazor.webassembly.js:1:32098
WASM: at Flurl.Http.FlurlRequest.HandleExceptionAsync (Flurl.Http.HttpCall call, System.Exception ex, System.Threading.CancellationToken token) <0x26945b8 + 0x001c2> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM: at Flurl.Http.FlurlRequest.SendAsync (System.Net.Http.HttpMethod verb, System.Net.Http.HttpContent content, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpCompletionOption completionOption) <0x2665d30 + 0x005e6> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM: at Flurl.Http.FlurlRequest.SendAsync (System.Net.Http.HttpMethod verb, System.Net.Http.HttpContent content, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpCompletionOption completionOption) <0x2665d30 + 0x0079a> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM: at Flurl.Http.HttpResponseMessageExtensions.ReceiveJson[T] (System.Threading.Tasks.Task`1[TResult] response) <0x26a2180 + 0x000d6> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM: at DotNetFabrik.FlurlExtensions.FlurlRequestExtensions.HandleWebApiExceptions[T] (System.Threading.Tasks.Task`1[TResult] task) <0x26a43f8 + 0x000e2> in <8c1e6df9d3f545cd831ff49915df2d85>:0 blazor.webassembly.js:1:32098
WASM: at DotNetFabrik.FlurlExtensions.FlurlRequestExtensions.HandleWebApiExceptions[T] (System.Threading.Tasks.Task`1[TResult] task) <0x26a43f8 + 0x00264> in <8c1e6df9d3f545cd831ff49915df2d85>:0 blazor.webassembly.js:1:32098
WASM: at BlazorCoreDMSTools.CommunicationService.CommunicationService.SetTokenAsync (System.String token, System.String database, System.String serverUri) <0x260dc60 + 0x00d9e> in <cb925648b50340888772566fbaeac465>:0

Just for some background, the Blazor team is in the process of significantly reducing the app's footprint, and resorting to some unusual measures to do so. In a nutshell, they've reduced it by about 20% by "wiping" HttpClientHandler.
wipe means "replace specified method bodies with a single throw
instruction". Doing this (instead of actually removing the method
entirely) means that the assembly retains a completely standard API
surface, and if you try to use one of the wiped methods, you get an
easy-to-understand exception stack trace that tells you which wiped
method you're trying to call.
This is what you've bumped up against: Blazor is still aware of HttpClientHandler for compilation purposes, but will throw a runtime exception if you (or in this case a compatible library) try to use it.
But HttpClient must wrap some implementation of HttpMessageHandler Blazor has its own: BrowserHttpMessageHandler. And Flurl provides an easy way to swap this in via its HttpClientFactory. But you don't need to pass in an HttpClient instance or implement CreateHttpClient. Instead, inherit from DefaultHttpClientFactory and just override CreateMessageHandler:
private class HttpClientFactoryForBlazor : DefaultHttpClientFactory
{
public override HttpMessageHandler CreateMessageHandler()
{
return new BrowserHttpMessageHandler();
}
}
I'd also recommend registering this once globally on app startup, rather than every time you create a FlurlClient:
FlurlHttp.Configure(settings =>
{
settings.HttpClientFactory = new HttpClientFactoryForBlazor();
});
It should also be noted that Blazor is still experimental and that BrowserHttpMessageHandler may be deprecated in a future release, so expect that this could be just a temporary work-around.

Currently in my 3.0 preview 5, BrowserHttpMessageHandler is not there anymore. Here is my current fix by simply not using any HttpMessageHandler. As far as I am aware, no problem happens to me yet, but I am not sure in all use cases:
class BlazorHttpClientFactory : DefaultHttpClientFactory
{
public override HttpClient CreateHttpClient(HttpMessageHandler handler)
{
return new HttpClient();
}
public override HttpMessageHandler CreateMessageHandler()
{
return null;
}
}

Related

EF Core error: The connection does not support MultipleActiveResultSets

I search thru all the links which had solution for the error. But, none of them were applicable for me as I had asynchronous code already and doing everything they have suggested.
We have Azure Functions based on .NET Core 3.1. We use latest version of Entity Framework Core. We are intermittently getting this error:
System.InvalidOperationException: The connection does not support MultipleActiveResultSets.
at Microsoft.Data.SqlClient.SqlCommand.<>c.b__164_0(Task1 result) at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
End of stack trace from previous location where exception was thrown
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
End of stack trace from previous location where exception was thrown ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func4 operation, Func4 verifySucceeded, TState state, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func4 operation, Func4 verifySucceeded, TState state, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 source, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 source, CancellationToken cancellationToken)
When we looked at the logs in AppInsights, we found that the exceptions occurred at the same time with exact same error for same function at the same place. But, it was for three different invocations (InvocationId) but same host instance (HostInstanceId) and different operation Id (Operation ID). Expectation is that for every new invocation, new dbContext will be instantiated as the AddDbContextPool adds scoped dbContext as dependency by default. Not sure if we can deduct anything out of it.
Below is our implementation approach. Appreciate any help on this. Thanking in advance.
We add DbContext to the services using following statement in the startup file:
builder.Services.AddDbContextPool<OurDbContext>(options =>
{
options.UseSqlServer("connectionstring"), builder =>
{
builder.EnableRetryOnFailure(3, TimeSpan.FromSeconds(2), null);
});
});
OurDbContext class has the following constructor:
public OurDbContext(DbContextOptions<OurDbContext> options)
: base(options)
{
}
And then we inject OurDbContext class in different repositories which uses this context to talk to SQL. Similar to below:
public class TypesRepo : RepoBase<Types>, ITypesRepo
{
public TypesRepo(OurDbContext ourDbContext) : base(ourDbContext)
{
}
public async Task RetrieveTypesAsync(List<string> types)
{
var records = await RetrieveConditionAsync(x => types.Contains(x.Type));
return records?.Select(x => new { x.Type, x.TypeId })
.ToDictionary(x => x.Type, x => x.TypeId);
}
}
public abstract class RepoBase<T> where T : class
{
protected OurDbContext OurDbContext { get; set; }
public RepoBase(OurDbContext OurDbContext)
{
this.OurDbContext = OurDbContext;
}
public async Task<List<T>> RetrieveConditionAsync(Expression<Func<T, bool>> expression)
{
return await OurDbContext.Set<T>().Where(expression).AsNoTracking().ToListAsync();
}
}
We inject above Repo class in Function classes and call above methods such as
await _typesRepo.RetrieveAsync()
P.S.: Based on below comment
I think dbcontextpool will reuse the dbcontext instance if it the connection is not active/unused but not the one which is active.
AddDbContext or AddDbContextPool
Your connection string needs to specify MultipleActiveRecordSets=true; to tell SqlServer to make sure this feature is enabled on the connections you make to it.
For example:
Data Source=localhost;Initial Catalog=master;Integrated Security=True;MultipleActiveResultSets=True
More info here: https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets
We recently ran into a similar issue, and it was due to having a request spin up multiple threads simultaneously, and each thread was using the same DbContext to parallelize a heavy database query.
Further, we use DbReader for working with the results, and that locks up the connection until the reader is disposed of.
That prevents the other threads, which are re-using the same DbContext / connection instance, which also are using DbReader to process results.
Enabling the multiple-active result sets feature solves this for us, and in our case, we actually do not notice a performance hit at all with this.

Correctly using of dependency injected DbContext to query Database

I have set up my own context using (as I believe is correct):
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<JobTrackingContext>(options => options.UseNpgsql(connection));
services.AddScoped<IJobRepository, JobRepository>();
}
Then I define my JobTrackingContext as follows:
public JobTrackingContext(DbContextOptions<JobTrackingContext> options)
: base(options)
{
public DbSet<Job> Jobs { get; set; }
}
Now I can define a repository to actually create/edit/delete Jobs:
public class JobRepository : GenericRepository<Job, long>, IJobRepository
{
private Job currentJob;
public JobRepository(JobTrackingContext jobTrackingContext, JobTrackingSettings settings)
: base(jobTrackingContext)
{
_settings = settings;
}
public async Task StartSync(JobType jobType, JobTriggerType jobTriggerType)
{
var tempJob = new Job(jobType, jobTriggerType);
await _dbContext.Jobs.AddAsync(tempJob);
await _dbContext.SaveChangesAsync();
}
}
And all this code gets instantiated by a Post-request to this API:
public async void Post()
{
_logger.LogDebug("Going to start account sync");
await _jobRepository.StartSync(JobType.ZRequestSync, JobTriggerType.Scheduled);
try
{
await _sync.StartAsync();
await _jobRepository.ChangeSyncStatus(JobStatusType.Finished);
}
catch (Exception e)
{
_logger.LogError(e, "Error occured during sync :(");
await _jobRepository.ChangeSyncStatus(JobStatusType.Failed);
}
}
Yet when I do this, I get an Exception with the message Reset() called on connector with state Connecting. I do not understand where this comes from.
When I do not use the injected version, but instead do this:
using (var c = new JobTrackingContext())
{
var job = new Job(jobType, jobTriggerType)
await c.Jobs.AddAsync(job);
await c.SaveChangesAsync();
}
All seems to be working fine. It seems that the context gets disposed too early. But how can I prevent this and/or what am I missing?
The Full Stacktrace:
System.ObjectDisposedException
HResult=0x80131622
Message=Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__52.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at ZShared.JobRepository.<StartSync>d__4.MoveNext() in C:\Users\richa\Documents\Codes\Company\Product\Shared\Folder\JobRepository.cs:line 38
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ZAccountSyncService.AccountSyncController.<Post>d__4.MoveNext() in C:\Users\richa\Documents\Code\Company\Product\SubProduct\AccountSyncController.cs:line 32
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
The gist of the problem is the declaration of your AccountSyncController.Post method. You have async void Post() instead of async Task Post().
When there is no task, a request has nothing to await and ends before the call of method _sync.StartAsync() is completed. With an end of a request comes also the end of a lifetime scope. On lifetime scoped end, all instances with scoped lifetime get disposed. Thus, your context is disposed before you get to the call of SaveChanges method. And this is the cause of your exception.

SignalR notification using SqlScaleoutConfiguration gives random exception for Rebus.Transport.TransactionContext not serializable

I use:
SignalR 2.2.2 in SqlScaleoutConfiguration
Rebus 3.0.1
Some events stored in Rebus are handled by a notification hub and pushed to the clients using signalR.
Everything works fine, but this morning, after having published a new version, none of the clients received the "new version" message probably because of the following exception:
10:39:04.586| |ERROR| |ProcessId=8196| |ThreadId=5| |SignalR.SqlMessageBus| |Stream 0 : Error starting SQL notification listener: System.Runtime.Serialization.SerializationException: Type 'Rebus.Transport.TransactionContext' in Assembly 'Rebus, Version=3.0.1.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Server stack trace:
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList argsToSerialize)
at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage..ctor(IMethodCallMessage mcm)
at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.SmuggleIfPossible(IMessage msg)
at System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(IMessage reqMsg)
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 System._AppDomain.CreateInstance(String assemblyName, String typeName)
at System.Data.SqlClient.SqlDependency.CreateProcessDispatcher(_AppDomain masterDomain)
at System.Data.SqlClient.SqlDependency.ObtainProcessDispatcher()
at System.Data.SqlClient.SqlDependency.Start(String connectionString, String queue, Boolean useDefaults)
at Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.StartSqlDependencyListener()
The message in Rebus queue results as correctly handled.
The handler is this:
public async Task Handle(ApplicationVersionEvent message)
{
await
Clients.All.CheckApplicationVersion(new ApplicationCurrentVersionNotification
{
CurrentVersion = message.CurrentVersion
});
}
It was resolved by a restart, but I need to understand what happened.
I similar issues are:
https://github.com/SignalR/SignalR/issues/3401
https://github.com/SignalR/SignalR/issues/3404
SQL Query Notifications do not always work in scaleout setup (SQL Server)
https://github.com/rebus-org/Rebus/issues/493
Rebus, exception when creating AppDomain / Instance from async Handler
but I think this is not the same case.
It is really hard for me to tell you what's going on here besides what you have already discovered: SignalR for some weird reason seems to want to serialize the values stashed in the current execution context, and one of those values is Rebus' current transaction context.
As explained in the links you included, Rebus stores an "ambient transaction" this way when handling a message, allowing all of its own operations to be enlisted in the same unit of work.
You could use the approach explained here, where the transaction context is temporarily removed in a safe way like this
public async Task Handle(SomeMessage message)
{
var transactionContext = AmbientTransactionContext.Current;
AmbientTransactionContext.Current = null;
try
{
JuggleWithAppDomainsInHere();
}
finally
{
AmbientTransactionContext.Current = transactionContext;
}
}
possibly moving relevant bits to the constructor/Dispose method respectively in a class that implements IDisposable, making for a smoother API:
using(new DismantleAmbientRebusStuff())
{
JuggleWithAppDomainsInHere();
}
I think someone who knows a lot about SignalR would need to chime in if we were to find out what really happened.
I forgot this issue, but I solved it by a workaround a little later on.
The clue is that SqlMessageBus serializes the context when it is initialized and this happens the first time it is retrieved invoking GetHubContext, so I forced its initialization before executing any command.
app.MapSignalR();
var context = new OwinContext(app.Properties);
var token = context.Get<CancellationToken>("host.OnAppDisposing");
if (token != CancellationToken.None)
{
token.Register(() =>
{
log.Info("host.OnAppDisposing");
// code to run when server shuts down
BackendMessageBusConfig.DisposeContainers();
});
}
// this code brings forward SignalR SqlMessageBus initialization
var forceInit = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
BackendMessageBusConfig.Register();

HttpContext.GetService in Mono

I've got the following code (lifted from here), and I'm trying to run it on a linux server w/ mono 2.10.5.
private static HttpContext GetCurrentContext(ControllerContext context) {
var currentApplication = (HttpApplication)context.HttpContext.GetService(typeof(HttpApplication));
if (currentApplication == null) {
throw new NullReferenceException("currentApplication");
}
return currentApplication.Context;
}
When running on mono, I get the following exception, which is straightforward enough:
System.NotImplementedException: The requested feature is not
implemented. at System.Web.HttpContextWrapper.GetService
(System.Type serviceType) [0x00000] in <filename unknown>:0
Is there a known workaround I can use to accomplish the same result on mono?
Not sure about the GetService method in Mono but the code you have lifted could be shortened like this:
private static HttpContextBase GetCurrentContext(ControllerContext context) {
return context.HttpContext;
}
You don't really need to go through the Application in order to fetch the HttpContext when you have direct access to it. I have also changed the return type to HttpContextBase instead of HttpContext because in ASP.NET MVC it is recommended to always work with abstractions. It makes your code more weakly coupled and unit testable.
Or if for some unknown to me reason you want to work with an actual HttpContext (no idea why someone would like to tie his code to it) you could try the following:
private static HttpContext GetCurrentContext(ControllerContext context) {
return context.HttpContext.ApplicationInstance.Context;
}
But as you can see in both cases the existence of this GetCurrentContext static method becomes quite questionable.

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