Hello stackoverflow gurus.
I have an XML request with body like this:
{<Policy xmlns="http://schemas.datacontract.org/2004/07/CompanyThatWroteBillingSoftware.BusinessObjects"><EffectiveDate>2023-01-25T00:00:00</EffectiveDate><ExpirationDate>2024-01-25T00:00:00</ExpirationDate><PaymentPlanId>2</PaymentPlanId><PolicyId>QC103986</PolicyId><PolicyStatus>Quote</PolicyStatus><SourceSystem>USERNAME</SourceSystem></Policy>}
This parses successfully in all online XML parsers I've tried. But when this request hits billing server it throws this exception:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"><EventID>131075</EventID><Type>3</Type><SubType Name="Error">0</SubType><Level>2</Level><TimeCreated SystemTime="2023-01-17T15:47:07.4196570Z" /><Source Name="System.ServiceModel" /><Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /><Execution ProcessName="w3wp" ProcessID="18172" ThreadID="94" /><Channel/><Computer>SERVERNAME</Computer></System><ApplicationData><TraceData><DataItem><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier><Description>Throwing an exception.</Description><AppDomain>/LM/W3SVC/2/ROOT/api-2-133184439071488997</AppDomain><Exception><ExceptionType>System.Runtime.Serialization.SerializationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Unable to deserialize XML body with root name 'Policy' and root namespace 'http://schemas.datacontract.org/2004/07/CompanyThatWroteBillingSoftware.BusinessObjects' (for operation 'ChangePaymentPlan' and contract ('Services', 'http://tempuri.org/')) using DataContractSerializer. Ensure that the type corresponding to the XML is added to the known types collection of the service.</Message><StackTrace> at System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.ReadObject(Message message)
Content type is 'application/xml' and content length is correct.
This same action from the server is functional on other machines with identical code. There must be some kind of data or versioning issue here. Any insight is welcome; I have never used SOAP endpoints before working on this.
Related
I have a very frustrating NServiceBus problem that I cannot seem to figure out. I am hoping that you guys can shed some light on the situation.
I am currently using NServiceBus.Core v5.0 and NServiceBus.Host v6.0 and running it in Unobtrusive Mode.
It seems that no matter what configuration I use, I always get some kind of error. I will start with the configuration that produces the least problems:
Case 1 - Using custom assembly scanning:
public void Customize(BusConfiguration configuration)
{
var endpointName = typeof(EndpointConfig).Namespace;
configuration.SetUniqueHostId(endpointName);
configuration.UseSerialization<JsonSerializer>();
configuration.UsePersistence<NHibernatePersistence, StorageType.Outbox>();
configuration.AssembliesToScan(new List<Assembly>
{
GetType().Assembly,
typeof(ICustomCommand).Assembly
});
configuration.Conventions()
.DefiningCommandsAs(type => typeof(ICustomCommand).IsAssignableFrom(type));
configuration.EnableDurableMessages();
configuration.EnableInstallers();
var container = ContainerInitializer.Container;
configuration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
}
The issues I have noticed here are the following:
When starting the NServiceBus host application and the persistence SQL database does not yet exist, no exception is thrown saying that the database cannot be found (it does in case 2).
I keep getting the following exception:
NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver Failed to fetch timeouts from the timeout storage
Which ultimately results in the application crashing because when this error occurs too many times, ServiceBus decides that enough is enough and just throws a fatal exception.
Besides the issues above, the application runs perfectly receiving and processing messages... until the fatal exception occurs
Now, this one is a bit more difficult:
Case 2 - Using default assembly scanning:
public void Customize(BusConfiguration configuration)
{
var endpointName = typeof(EndpointConfig).Namespace;
configuration.SetUniqueHostId(endpointName);
configuration.UseSerialization<JsonSerializer>();
configuration.UsePersistence<NHibernatePersistence, StorageType.Outbox>();
// !! DISABLED !!
// configuration.AssembliesToScan(new List<Assembly>
// {
// GetType().Assembly,
// typeof(ICustomCommand).Assembly
// });
configuration.Conventions()
.DefiningCommandsAs(type => typeof(ICustomCommand).IsAssignableFrom(type));
configuration.EnableDurableMessages();
configuration.EnableInstallers();
var container = ContainerInitializer.Container;
configuration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
}
In this case the following issues occur:
When the persistence SQL database does not yet exist:
When starting the NServiceBus host application and the SQL database does not exist, an exception is throw - Expected behavior (This is positive)
After creating the persistence SQL database:
ServiceControl.Plugin.Nsb5.Heartbeat.Heartbeats|Unable to send heartbeat to ServiceControl:
NServiceBus.Unicast.Queuing.QueueNotFoundException: Failed to send message to address: [Particular.ServiceControl#MYPCNAME]
Exception thrown: 'System.Messaging.MessageQueueException' in System.Messaging.dll
Additional information: External component has thrown an exception.
2017-09-15 16:25:45.6743|Warn|NServiceBus.Unicast.Messages.MessageMetadataRegistry|Message header 'SharedTemp.Interfaces.ICustomCommand'
was mapped to type 'SharedTemp.Interfaces.ICustomCommand' but that type was not found in the message registry [...]
Exception thrown: 'System.Exception' in NServiceBus.Core.dll
Additional information: Could not find metadata for 'Newtonsoft.Json.Linq.JObject'.
Now, exceptions 3 and 4 are particularly (no pun intended) odd since the NServiceBus documentation states:
By default all assemblies in the endpoint bin directory are scanned to find types implementing its interfaces so that it can configure them automatically.
And the "Newtonsoft.Json" and my "SharedTemp dll's" are indeed in the BIN folder, but NServiceBus does not seem to find them. As for point 1: NServiceBus does not create that queue for me, but it creates all the other queues that I need.
Finally the always requested app.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="MasterNodeConfig" type="NServiceBus.Config.MasterNodeConfig, NServiceBus.Core"/>
<section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core"/>
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core"/>
<section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core"/>
</configSections>
<appSettings>
<add key="NServiceBus/Persistence/NHibernate/dialect" value="NHibernate.Dialect.MsSql2012Dialect"/>
<add key="NServiceBus/Outbox" value="true"/>
</appSettings>
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
<UnicastBusConfig>
<MessageEndpointMappings />
</UnicastBusConfig>
<AuditConfig QueueName="audit"/>
<connectionStrings>
<add name="NServiceBus/Persistence" connectionString="Server=(LocalDB)\v11.0;Initial Catalog=NServiceBus;Integrated Security=true"/>
</connectionStrings>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri=""/>
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400"/>
</providers>
</roleManager>
</system.web>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
<MasterNodeConfig Node="localhost"/>
</configuration>
Does anyone have an idea about any of this?
After a lot of searching I finally found the problem!
First of all I was using a in-house NuGet package that was supposed to help me with configuring NServiceBus. The package worked fine for other projects, but for mine not so well, since I was using JsonSerialization instead of the default XML serialization.
The first problem with the package is that it used the "INeedInitialization" interface to configure NServiceBus. In my code I would then call "IConfigureThisEndpoint" to enable the JsonSerialization. The issue here was, that when starting the NServiceBus host, it would fail to find the NewtonSoft.Json library. If I then added custom assembly scanning to my own configuration code, it would not trigger "INeedInitialization", causing an incomplete/incorrect configuration.
I assume it could not load the NewtonSoft.Json library because scanning was triggered in the code/namespace of the package? Maybe #Sean Farmer can answer this?
The second problem with the package is that it would add connection strings to the app.config, one for "NServiceBus/Persistence" and one for "NServiceBus/Persistence/NHibernate/Saga". I am not using Saga, so the connection string for that was not needed. Initially this was not a problem since I caught it the first time, but I completely forgot about it after reinstalling the package. Removing this again also seemed to make NServiceBus happier.
So, what ended up working? I removed the package and did the configuration myself with the following result:
public void Customize(BusConfiguration configuration)
{
var endpointName = typeof(EndpointConfig).Namespace;
configuration.UniquelyIdentifyRunningInstance().UsingCustomIdentifier(endpointName);
configuration.EnableOutbox();
configuration.UsePersistence<NHibernatePersistence>();
configuration.Transactions().DefaultTimeout(TimeSpan.FromMinutes(5.0));
configuration.UseSerialization<JsonSerializer>();
configuration.Conventions()
.DefiningCommandsAs(type => typeof(ICustomCommand).IsAssignableFrom(type));
configuration.EnableDurableMessages();
configuration.EnableInstallers();
var container = ContainerInitializer.Container;
configuration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
}
#Sean: Thank you for allowing me to contact you. Luckily it was not necessary
#Mike: Thank you for the input
I'm new to microsoft azure service fabric. For my master's degree I have to develop a microservice-approach prototype in service fabric. After hours of researching I am still not getting my issue(s) solved.
I want to access my (in a local fabric cluster deployed) stateless service in a web front-end like in https://azure.microsoft.com/en-us/documentation/articles/service-fabric-add-a-web-frontend/. The simplest way for doing that is by adding an ASP .NET 5 Web Api project to the Service Fabric application and make a ServiceProxy method call in the ValuesController. So I added this code to my solution:
ValuesController.cs:
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values/IObject
[HttpGet("{interfaceName}")]
public async Task<string> Get(string interfaceName)
{
var serviceName = "fabric:/DataServiceFabric/MasterDataMService";
var masterDataService = ServiceProxy.Create<IMasterDataMService>(new Uri(serviceName));
var result = await masterDataService.GetMasterDataByName(interfaceName);
return result.Content;
}
}
After a F5-deploy my browser doesn't automatically navigate to my web front-end. By looking into the Service Fabric Explorer my ASP .NET 5 application throws a Health State error:
Kind Health State Description
=============================================================================
Partitions Error Unhealthy partitions: 100% (1/1), MaxPercentUnhealthyPartitionsPerService=0%.
Partition Error Unhealthy partition: PartitionId='413...', AggregatedHealthState='Error'.
Event Error Error event: SourceId='System.FM', Property='State'. Partition is below target replica or instance count.
After this this question the "Partition is below target replica or instance count" indicates that a unhandled exception in my service is preventing it from starting. But I'm not able to find a stack strace in my Service Fabric Explorer to debug this failure. This is my ServiceManifest.xml of my ASP .NET web service:
ServiceManifest.xml (Web1):
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="Web1" Version="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<ServiceTypes>
<StatelessServiceType ServiceTypeName="Web1Type">
<Extensions>
<Extension Name="__GeneratedServiceType__">
<GeneratedNames xmlns="http://schemas.microsoft.com/2015/03/fabact-no-schema">
<DefaultService Name="Web1Service" />
<ServiceEndpoint Name="Web1TypeEndpoint" />
</GeneratedNames>
</Extension>
</Extensions>
</StatelessServiceType>
</ServiceTypes>
<CodePackage Name="C" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>approot\runtimes\dnx-clr-win-x64.1.0.0-rc1-update1\bin\dnx.exe</Program>
<Arguments>--appbase approot\src\Web1 Microsoft.Dnx.ApplicationHost Microsoft.ServiceFabric.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener</Arguments>
<WorkingFolder>CodePackage</WorkingFolder>
<ConsoleRedirection FileRetentionCount="5" FileMaxSizeInKb="2048" />
</ExeHost>
</EntryPoint>
</CodePackage>
<Resources>
<Endpoints>
<Endpoint Name="Web1TypeEndpoint" Protocol="http" Type="Input" Port="80" />
</Endpoints>
</Resources>
</ServiceManifest>
And here my ApplicationManifest.xml of my service fabric solution:
ApplicationManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="DataServiceFabricType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="ActorTestServiceActorService_PartitionCount" DefaultValue="10" />
<Parameter Name="MasterDataMService_InstanceCount" DefaultValue="-1" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="Web2Pkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="Web1" ServiceManifestVersion="1.0.0" />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="ActorTestServicePkg" ServiceManifestVersion="1.0.0" />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MasterDataMServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<DefaultServices>
<Service Name="Web1Service">
<StatelessService ServiceTypeName="Web1Type">
<SingletonPartition />
</StatelessService>
</Service>
<Service Name="ActorTestServiceActorService" GeneratedIdRef="761ee3cf-5a3a-49d8-9c57-aa3480d1acf1">
<StatelessService ServiceTypeName="ActorTestServiceActorServiceType">
<UniformInt64Partition PartitionCount="[ActorTestServiceActorService_PartitionCount]" LowKey="-9223372036854775808" HighKey="9223372036854775807" />
</StatelessService>
</Service>
<Service Name="MasterDataMService">
<StatelessService ServiceTypeName="MasterDataMServiceType" InstanceCount="[MasterDataMService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
So I created a new solution with an ASP.NET 5 web application and the same ValuesController.cs. I ensured my stateless service is running on my local cluster and than I started my new web application. After calling the GET-Method in my Controller I got the following exception:
Exception thrown: 'System.Fabric.FabricException' in mscorlib.dll
Microsoft.AspNet.Hosting.Internal.HostingEngine: Information: Request finished in 0,2593ms 500
Microsoft.AspNet.Server.Kestrel: Error: An unhandled exception was thrown by the application.
System.Fabric.FabricException: Invalid partition key/ID '{0}' for selector {1}
My stateless service is a SingletonPartition, so do I need a partition key here? And if yes, how do I get the key? The Service Fabric Explorer doesn't provide me with this information for my stateless service. Here is the ServiceManifest.xml of my stateless service:
ServiceManifest.xml (MasterDataMService):
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="MasterDataMServicePkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="MasterDataMServiceType" />
</ServiceTypes>
<!-- Code package is your service executable. -->
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>MasterDataMService.exe</Program>
</ExeHost>
</EntryPoint>
</CodePackage>
<!-- Config package is the contents of the Config directoy under PackageRoot that contains an
independently-updateable and versioned set of custom configuration settings for your service. -->
<ConfigPackage Name="Config" Version="1.0.0" />
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="ServiceEndpoint" Type="Input" Protocol="http" Port="80"/>
</Endpoints>
</Resources>
</ServiceManifest>
After that I decided to set up a service communication with OWIN:
MasterDataMService.cs:
internal sealed class MasterDataMService : StatelessService, IMasterDataMService
{
[...]
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(initParams => new OwinCommunicationListener("MasterDataMService", new StartUp(), initParams))
};
}
}
Now I can acess my microservice by using a HttpClient in my DefaultController:
var client = new HttpClient();
var request = "http://localhost:80/MasterDataMService/api/values/query";
var result = string.Empty;
HttpResponseMessage response = await client.GetAsync(request);
if (response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsStringAsync();
}
But thats not what I originally wanted. I don't want to specifiy the service endpoint in my request. Instead I would like to communicate with my stateless service over a ServiceProxy. How do I achieve that here? What did I wrong? And how can I solve this Health State error with my ASP .NET 5 application which is deployed into my service fabric cluster?
Thanks for your time.
Edit:
Extended stacktrace of invalid partition key exception:
Exception thrown: 'System.Fabric.FabricException' in mscorlib.dll
Microsoft.AspNet.Hosting.Internal.HostingEngine: Information: Request finished in 1,35ms 500
Microsoft.AspNet.Server.WebListener.MessagePump: Error: ProcessRequestAsync
System.Fabric.FabricException: Invalid partition key/ID '{0}' for selector {1} ---> System.Runtime.InteropServices.COMException: exception of HRESULT: 0x80071BBF
at System.Fabric.Interop.NativeClient.IFabricServiceManagementClient4.EndResolveServicePartition(IFabricAsyncOperationContext context)
at System.Fabric.FabricClient.ServiceManagementClient.ResolveServicePartitionEndWrapper(IFabricAsyncOperationContext context)
at System.Fabric.Interop.AsyncCallOutAdapter2`1.Finish(IFabricAsyncOperationContext context, Boolean expectedCompletedSynchronously)
--- End of inner exception stack trace ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Services.Client.ServicePartitionResolver.<ResolveAsyncHelper>d__2a.MoveNext()
--- End of stack trace from the previous location where the exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Services.Communication.Client.CommunicationClientFactoryBase`1.<GetClientAsync>d__a.MoveNext()
Please give me feedback if you need more. (full stack trace is 82 lines long)
Invalid scheme exception stack trace:
Exception thrown: 'System.ArgumentException' in mscorlib.dll
Microsoft.AspNet.Hosting.Internal.HostingEngine: Information: Request finished in 1,45ms 500
Microsoft.AspNet.Server.WebListener.MessagePump: Error: ProcessRequestAsync
System.ArgumentException: the provided uri scheme 'http' is invalid; expected 'net.tcp'.
Parametername: via
at System.ServiceModel.Channels.TransportChannelFactory`1.ValidateScheme(Uri via)
at System.ServiceModel.Channels.ConnectionOrientedTransportChannelFactory`1.OnCreateChannel(EndpointAddress address, Uri via)
at System.ServiceModel.Channels.ChannelFactoryBase`1.InternalCreateChannel(EndpointAddress address, Uri via)
at System.ServiceModel.Channels.ServiceChannelFactory.ServiceChannelFactoryOverDuplexSession.CreateInnerChannelBinder(EndpointAddress to, Uri via)
at System.ServiceModel.Channels.ServiceChannelFactory.CreateServiceChannel(EndpointAddress address, Uri via)
at System.ServiceModel.Channels.ServiceChannelFactory.CreateChannel(Type channelType, EndpointAddress address, Uri via)
at System.ServiceModel.DuplexChannelFactory`1.CreateChannel(InstanceContext callbackInstance, EndpointAddress address, Uri via)
at System.ServiceModel.DuplexChannelFactory`1.CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress)
at Microsoft.ServiceFabric.Services.Communication.Wcf.Client.WcfCommunicationClientFactory`1.<CreateClientAsync>d__2.MoveNext()
--- End of stack trace from the previous location where the exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Services.Communication.Client.CommunicationClientFactoryBase`1.<CreateClientWithRetriesAsync>d__1e.MoveNext()
I ran into the same problem while learning about Service Fabric. Turned out that providing just the URI was not enough - I also had to specify the partition key as a magic value of one:
IHelloService service = ServiceProxy.Create<IHelloService>(new Uri("fabric:/Application1/HelloService"), new ServicePartitionKey(1));
Kudos to this thread on disq.us. There is also a deeper explanation provided by a Microsoft engineer Oana Platon as to why the value of 1 works:
Diogo, take a look at this article that explains partitioning:
link Specifically, look at ranged
partitioning (otherwise known as UniformInt64Partition): "This is used
to specify an integer range (identified by a low key and high key) and
a number of partitions (n). It creates n partitions, each responsible
for a non-overlapping subrange of the overall partition key range. For
example, a ranged partitioning scheme with a low key of 0, a high key
of 99, and a count of 4 would create four partitions, as shown below."
Then look at your service manifest and figure out how it is configured
- how many partitions and what is the range (low key - high key). If you have one partition, any key in that range goes to the (one)
partition, so it doesn't matter which key you specify. If you have
more than one partition, you need to figure out with which one your
client needs to talk to. Specify a partition key in the range that
partition is serving.
I must admit that I myself must study partitioning in greater depth to understand this explanation.
In the getting started examples, there is a class ServiceUriBuilder. Initialize this class by passing the service name in the constructor.
var proxyLocation = new ServiceUriBuilder("MasterDataMService");
var masterDataService = ServiceProxy.Create<IMasterDataMService>(proxyLocation.ToUri());
var result = await masterDataService.GetMasterDataByName(interfaceName);
Also in your MasterDataMService CreateServiceInstanceListeners method, make sure it looks something like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[] { new ServiceInstanceListener(context => new FabricTransportServiceRemotingListener(context, this)) };
}
I ran in to exactly the same problem using ServiceProxy with a Stateless Service. I have a Stateful Services that works well, but the Stateless was receiving:
System.Fabric.FabricException: Invalid partition key/ID '{0}' for selector {1}
As Allan T mentions above, you also need to use the third constructor overload for ServiceProxy.Create():
Instead of:
ServiceProxy.Create<IMasterDataMService>(0, new Uri("fabric:/DataServiceFabric/MasterDataMService"));
use:
ServiceProxy.Create<IMasterDataMService>(new Uri("fabric:/DataServiceFabric/MasterDataMService"));
...simply, do not specify the partition. That made the error go away for me.
https://msdn.microsoft.com/en-us/library/mt628402.aspx
I ran into these same frustrating issues myself and resolved them.
A couple of things to check
1) Make sure your ASP.NET 5 web api project is not referencing any X64 libraries.
2) Port Clash.. when deploying your ASPNET 5 web api to the Cluster, make sure there are no 2 websites that are using the same port. You can change the port inside the [ASP.NET 5 project]/PackageRoot/ServiceManifest.xml.. towards the bottom
**3) "wrap" folder madness! Verify that your wrap folder (at the root solution folder) only contains your .net 4.5.1 class libraries. My issues went away when I deleted the "Newtonsoft.Json" folder inside the wrap folder. You will then have to run dnu restore on the solution so it will recreate the project.lock.json files
4) Make sure nothing is blowing up inside your startup.cs class. Run the web api locally just to make sure its loading; its normal that the service proxy class will fail to load.
Judging by your second stack trace:
System.ArgumentException: the provided uri scheme 'http' is invalid; expected 'net.tcp'.
It looks like you're trying to use ServiceProxy to connect to a service that is listening on an HTTP endpoint. ServiceProxy expects a Service Remoting Listener which uses a binary protocol, not HTTP.
The first exception is still a bit of a mystery:
System.Fabric.FabricException: Invalid partition key/ID '{0}' for selector {1}
This will only happen if you attempt to resolve a uniform int64 or named partitioned service without providing a partition key. In your config it appears you have the target service set up as a singleton partition, in which case you should not see this error, so can you double-check that the service you are trying to connect to is in fact created as a singleton partition service?
In my case, none of the above worked. Or more precisely, my solution was a combination/variation of the above solutions
I needed to do 2 things: First, make sure I have registered my services:
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new[] { new ServiceReplicaListener(context => this.CreateServiceRemotingListener(context)) };}
And second, refer to the very first service ("magic" value of 0)
ServiceProxy.Create<IMasterDataMService>(new Uri("fabric:/DataServiceFabric/MasterDataMService"), new ServicePartitionKey(0));
I hope this helps
I am trying to modify and add custom headers to a soap message in the BeforeSendRequest method like this:
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
MessageHeader header = MessageHeader.CreateHeader("name", "http://myname", "Oscar");
request.Headers.Add(header);
return null;
}
Everything is ok at this point, the header is added in the soap headers like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="51efbfdb-2187-45b9-81fc-6a38815d5bed" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">d1351a78-a53a-4d32-ad35-fca6d4262adf</ActivityId>
<name xmlns="http://myname">Oscar</name>
</s:Header>
The problem is that I want to add something bigger in the headers and the final result has to be like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="51efbfdb-2187-45b9-81fc-6a38815d5bed" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">d1351a78-a53a-4d32-ad35-fca6d4262adf</ActivityId>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">username</wsse:Username>
<wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</s:Header>
Is there a way to achieve this?
PS. Please guys :-) do not criticize me, I am in the following situation:
When adding this username and password auth, you need to be over https, the problem is that this Java based webservice which I am trying to communicate is under http and I think it is not compliant because according to the 3rd link "It is considered bad practice to pass credentials over an unsecured connection" but they solved it adding the headers in the config file (something I did without success).
I read these links too and tried them. Also when doing things from links 1 and 2, I got a kind of exception in Visual Studio which says something like "It is expected https and not http" that's why I am trying MessageInspectors using BeforeSendRequest method.
Configure WCF for WS-Security with Username over https
http://www.west-wind.com/weblog/posts/2007/Dec/09/Tracing-WCF-Messages
http://www.fransson.net/blog/credentials-over-plain-http-with-wcf/
ClearUsernameBinding is the solution
The 3rd parameter of CreateHeader is an object. By default this object is serialized using the DataContractSerializer so if you create a data contract that models the header structure you can pass an instance as the 3rd parameter and it will create the header you want
I had the same problem, though my service was https. And it should be a configuration matter, you shouldn't need to handle this manually.
Anyway, you don't have to use the MessageInspectors using BeforeSendRequest.
You should try and change the config generated code adding some security configuration.
WCF will then create what headers you need. Then in code add the credentials and you should be ok.
I imagine that the generated proxy is creating you a customBinding or basicHttpBinding.
basicHttpBinding though not supporting the WS-Security specifications, so you should change this either to custom or wsHttpBinding. You can play with and find the correct configuration to gain the desired results.
What I added was "Sample config syntax":
<customBinding>
<binding name="MessageServerBinding">
<security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<secureConversationBootstrap />
</security>
........
</binding>
</customBinding>
This is a sample configuration, e.g. you might not need to include a timestamp, or you could need a Nonce which if I remember correctly needs some more effore, not much though.
For check this discussion: WCF: Adding Nonce to UsernameToken
Hope this helps.
I've got a ServiceContract that has an OperationContract with the following method signature: Manipulate(int fileid, param object[] operations).
I also have five DataContracts defined for the WCF service, and I'd like object[] operations to accept any number and combination of those. The problem is that they aren't visible unless I use them in the method signature. If I do that though, then only one type of DataContract can be used at a time, defeating the purpose of using an object[].
How do I make all five DataContracts visible on the client side without having to alter the method signature?
Use known types. For example in your config file you could define the different known types:
<configuration>
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type="System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<knownType type="SomeNs.Foo, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXX" />
<knownType type="SomeNs.Bar, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXX" />
<knownType type="SomeNs.Baz, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXX" />
</add>
</declaredTypes>
</dataContractSerializer>
</system.runtime.serialization>
</configuration>
Now clients will know about the Foo, Bar and Baz data contracts.
This being said, I would recommend you to use a common base type for your data contracts instead of object. Having a method signature that takes object as input is hard to understand from a consumer standpoint.
I'm trying to expose an existing RIA service with SOAP and JSON.
In the web.config, serviceModel section, I've put:
<system.serviceModel>
<domainServices>
<endpoints>
<add name="OData" type="System.ServiceModel.DomainServices.Hosting.ODataEndpointFactory, System.ServiceModel.DomainServices.Hosting.OData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="Soap" type="Microsoft.ServiceModel.DomainServices.Hosting.SoapXmlEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="Json" type="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</endpoints>
</domainServices>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
In MyDomainService there is:
[Query(IsDefault=true)]
public IEnumerable<UserItem> GetUsers()
{
return this.ObjectContext.Users;
}
I've tried the following URLs:
http://10.0.0.191:27070/Manager-Web-MyDomainService.svc/GetUsers
http://10.0.0.191:27070/Manager-Web-MyDomainService.svc/Soap/GetUsers
http://10.0.0.191:27070/Manager-Web-MyDomainService.svc/Json/GetUsers
http://10.0.0.191:27070/Manager-Web-MyDomainService.svc/OData/GetUsers
and I get just blank pages.
I've enabled tracing and in the log I see the warning "Configuration evaluation context not found".
Anybody who can help me with this?
Thanks in advance,
Cheers,
Gianluca.
Ok, I've sorted out almost everything. My configuration was correct. Problems were elsewhere. Let me share my findings:
First of all, I've found out that OData requires a '/' at the end of the URL. Also, I was wrongly thinking that it is necessary to recall the service URL with at the end the name of the method. Something like: http:///oData/. It turned out that by calling just http:///oData/ I was getting all the expected data.
At the contrary, Json does not want the trailing '/'. A correct URL is like: http:///Json/. This time it's been necessary to indicate the method. I'm also starting to understand better the meaning of the attributes Query, Invoke, etc. An INVOKE-decorated method is exposed as JSON only if it has the property HasSideEffect=false.
I am still having trouble exposing the same methods via SOAP. If someone wants to contribute and help me out, please feel free to add more info here. I'll post more information as soon as I get further results.
Cheers,
Gianluca.