WCF System.IndexOutOfRangeException in Dispatcher.DispatchOperationRuntime.InspectInputsCore - wcf

Issue: Getting below error while WCF service is invoked.
Index was outside the bounds of the array.
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InspectInputsCore(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
System.IndexOutOfRangeException
Need help to resolve this issue.
Details:
We have web-hosted (in same virtual directory, ASP.NET compatiblity enabled, baic http binding) multiple WCF services created as below
6 Services with individual service contracts for each service and respective datacontracts for each operations. Uses custom service host factory which adds a Message Inspector
2 services hosted in below fashion
2 seperate wsdls (design time files, with different schemas) pointing to the same service endpoint implementing the below contract. Uses a different custom service host factory which also adds a Message Inspector
[ServiceContract]
public interface IGenericService
{
[OperationContract(Action = "*", ReplyAction = "*")]
System.ServiceModel.Channels.Message GenericOperation(System.ServiceModel.Channels.Message msgRequest);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ValidateMustUnderstand = false)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GenericService : IGenericService
{
public Message GenericOperation(Message msgRequest)
{
All of these services are having proxies in SOA platform (Progress Actional). Actional maintains the direct endpoints for invoking the actual service and is able to properly invoke the actual service.
All 8 services are working fine in a server used for UnitTest execution. When deployed to QA servers all 6 services with individual service contracts work fine but the 2 new services (design time wsdls files) thow error listed above.
Code inside MessageInspector (failing services) looks as below. Other Inspector for other set of 6 services is similar.
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return Stopwatch.StartNew();
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Stopwatch watch = (Stopwatch)correlationState;
watch.Stop();
TimeSpan performanceTime = watch.Elapsed;
watch = null;
// Invoke Performance Logging Code
}
}
ServiceTrace looks as below.
Construct ServiceHost 'XyzServices.SpecificService' (One of the 6 service with individual service contract)
Open ServiceHost 'XyzServices.SpecificService'
All Endpoint listner opened for specific service
Listen at 'specificservice uri'
Processing message 1
Process action 'SpecificService.SpecificOperation.SoapAction'
Execute 'XyzServices.SpecificService.SpecificOperation'
Construct ServiceHost 'XyzServices.GenericService'
Processing message 2
From: Listen at 'XyzServices.SpecificService endpoint'
Activity boundary Start
To: Process action 'GenericService.GenericOperation.SoapAction'
To: Listen at 'XyzServices.SpecificService endpoint'
Activity boundary Stop
Open ServiceHost 'XyzServices.GenericService'
All Endpoint listner opened for Generic service
Process action 'GenericService.GenericOperation.SoapAction'
From: Processing message 2
Activity boundary Start
Received message over channel - Message header looks fine. Does not show message body
ServiceChannel information - Every thing looks fine here for (Unit Test server and QA server)
Handling an exception - shows the exception pasted in question details (only in QA server)
Sent a message over a channel
Aborted InstanceContext
Activity boundary Stop
(This activity looks fine when services run in Unit test server)
I used service trace viewer for the first time, but I noted that 'Processing message 2' activity starts from a activity which is related with the specific service. Does that indicate any problem in the way services are hosted. (where these services need separation)
Please let me know, if more details are needed.
this.InitializeCallContext(ref rpc);
object target = rpc.Instance;
this.DeserializeInputs(ref rpc);
**this.InspectInputs(ref rpc);**
ValidateMustUnderstand(ref rpc);
IAsyncResult result = null;
IDisposable impersonationContext = null;
IPrincipal originalPrincipal = null;
bool isThreadPrincipalSet = false;
try
{
if (this.parent.SecurityImpersonation != null)
{
this.parent.SecurityImpersonation.StartImpersonation(ref rpc, out impersonationContext, out originalPrincipal, out isThreadPrincipalSet);
}
void InspectInputsCore(ref MessageRpc rpc)
{
int offset = this.Parent.ParameterInspectorCorrelationOffset;
for (int i = 0; i < this.ParameterInspectors.Length; i++)
{
IParameterInspector inspector = this.ParameterInspectors[i];
rpc.Correlation[offset + i] = inspector.BeforeCall(this.Name, rpc.InputParameters);
}
}

Related

WCF Service unable to call from .NET Core

I am doing something wrong and I can't figure it out ... I made .NET Framework 4 console application to communicate with SOAP Service, with use of Topshelf I deployed service on a server and with simple URL access to a method or use of Boomerang tool, I can see service is returning value
URL: http://35.231.17.237:8066/ERPCommunicationService/OriginalService/IsServiceHealthy
But now, when I try to access same service, from .NET Core project, I keep getting error:
System.ServiceModel.ProtocolException:
The remote server returned an unexpected response: (405) Method Not Allowed.
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(
SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(
String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass1_0.
<CreateGenericTask>b__0(IAsyncResult asyncResult)
--- End of stack trace from previous location where exception was thrown ---
Code is simple, I successfully used service endpoint to connect it to .NET Core project, where I can see Reference.cs autogenerated file and all methods from service are there ...
Here is service call from client side (.net core):
public async Task<bool> IsServiceHealthy()
{
try
{
string servicesUrl = $"{_iConfiguration["servicesUrl"]}/IsServiceHealthy";
//My binding setup, since ASP.NET Core apps don't use a web.config file
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
binding.MaxReceivedMessageSize = 10485760;
binding.SendTimeout = new TimeSpan(0, 0, 0, 180);
binding.ReceiveTimeout = new TimeSpan(0, 0, 0, 180);
var rsExec = new OriginalService.OriginalServiceClient(binding,
new EndpointAddress(servicesUrl));
var clientFactory = rsExec.ChannelFactory.CreateChannel();
var response = await clientFactory.IsServiceHealthyAsync();
return response;
}
catch (Exception ex)
{
logging.LogError(ex.ToString());
throw ex;
}
}
And code from server side (.NET Framework 4):
Interface:
[OperationContract]
[WebInvoke(Method = "GET",
RequestFormat = WebMessageFormat.Json,
UriTemplate = "/IsServiceHealthy")]
bool IsServiceHealthy();
Implementation:
public bool IsServiceHealthy()
{
bool serviceResult = false;
byte[] test = new byte[200];
var client = new ChannelFactory<BisWebWS.BisWebWSSOAPPortType>("BisWebWSSOAPPort")
.CreateChannel();
BisWebWS.tauthStrct auth = ServisBasic.GetAuth();
try
{
var result = client.wsTest(new BisWebWS.wsTestRequest(test));
serviceResult = result.wsTestResult;
}
catch (Exception ex)
{
logger.LogError(ex.InnerException.ToString());
}
return serviceResult;
}
When ever I google shown error, everywhere it says its server side setup, but I am kinda stuck as I installed everything there is ... I am using MS Windows Server 2012 R2 Datacenter,
Thank you for shared idea how to fix this problem
The way that we call the service by using the proxy class is an Http Post request, while there is a GET decoration on the method. It requires an Http Get request instead of Post request. This might directly cause the issue.
[OperationContract]
[WebInvoke(Method = "GET",
RequestFormat = WebMessageFormat.Json,
UriTemplate = "/IsServiceHealthy")]
bool IsServiceHealthy();
If the server host the service by using Webhttpbinding, we could directly get the result by typing the service address in the browser address bar since the default request is an Http Get request (your link is not available).
This kind of service is called Restful-style service.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/wcf-web-http-programming-model
https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
The typical call is to construct an HTTP request with a request body by using HttpClient library.
We could also call the service by using the client proxy class, like what you do. However, we should keep the binding configuration consistent between the server and the client.
WCF: There was no endpoint listening at, that could accept the message
It is too complex to call the service by using client proxy class, it is better to send Http request with HttpClient when we call Restful style service.
Besides, we could also host the service by using BasicHttpBinding, this may simplify the call. There is no need to add webhttpendpoint behavior and no need to add additional [Webget] decorations.
Simply speaking, we should maintain the binding consistent between the server and the client when using client proxy.
Feel free to let me know if the problem still exists.

Can't get WCF service to send XML Document to BizTalk Receive Location

I'm new to BizTalk and WCF services and am trying to figure out how to use a WCF service to deliver XML data to Biztalk. I think I'm close but when I call the WCF service operation, the operation executes successfully but does not appear to generate any kind of a message in Biztalk. Am I wrong in assuming that simply calling an operation is enough to trigger a message to BizTalk?
Below is my code and some details about my BizTalk configuration:
WCF service:
public interface IService1
{
[OperationContract, XmlSerializerFormat]
XmlDocument GetXMLDocument(string sourceXML);
}
public class Service1 : IService1
{
public XmlDocument GetXMLDocument(string sourceXML)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(sourceXML);
return doc;
}
}
Calling application (button click calls the service):
protected void Button2_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateNode(XmlNodeType.Element, "Patients", "test"));
SendDoc(doc);
}
protected void SendDoc(XmlDocument doc)
{
//use a Service Client Object to call the service
objServiceClientobjService.GetXMLDocument(doc.OuterXml);
}
BizTalk configuration:
Receive Port:
Port type: One-Way
Receive Location:
Type: WCF-Custom with basicHTTP binding
Endpoint Address is the same as the IIS hosted WCF Service
Receive Pipeline Type: XMLReceive
Your implementation is not correct. There is no link between your WCF service and BizTalk. If you want to receive xml in BizTalk then you need to expose either an Orchestration or Xml Schema as WCF service using BizTalk WCF Web Service Publishing Wizard. This gets installed with BizTalk. Please see link for more details: msdn link
The solution I always use, is to expose an endpoint. Take a look at this example:

WCF Discovery and DataService V3

I would like to expose discovery endpoints (both TCP and UDP) for my Data Services v3 and enable services to be discoverable from the client and discover them in another application. The main point in the discovery is to get the service endpoint address at the client.
I have tried to adapt the samples that Microsoft have provided for WCF Discovery, but so far I failed to achieve my goal.
I have created a custom Data Service Host Factory on server side:
public class CustomDataServiceHostFactory : System.Data.Services.DataServiceHostFactory
{
protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var serviceHost = base.CreateServiceHost(serviceType, baseAddresses);
EndpointDiscoveryBehavior endpointDiscoveryBehavior = new EndpointDiscoveryBehavior();
// Create XML metadata to add to the service endpoint
XElement endpointMetadata = new XElement(
"Root",
new XElement("Information", "This endpoint is Data Service v3!"),
new XElement("Time", System.DateTime.Now.ToString("MM/dd/yyyy HH:mm")));
// Add the XML metadata to the endpoint discovery behavior.
endpointDiscoveryBehavior.Extensions.Add(endpointMetadata);
//may be this is not the safest way to set the behaviour
foreach (var endpoint in serviceHost.Description.Endpoints)
{
endpoint.Behaviors.Add(endpointDiscoveryBehavior);
}
// Make the service discoverable over UDP multicast
serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
return serviceHost;
}
}
On the client side I have tried the following code:
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
// Find service endpoints
// ServiceReference.DataModel is the generated class for the Data Service client proxy
FindCriteria findCriteria = new FindCriteria(typeof(ServiceReference.DataModel));
findCriteria.Duration = TimeSpan.FromSeconds(30);
FindResponse findResponse = discoveryClient.Find(findCriteria);
// Check to see if endpoints were found & print the XML metadata in them.
if (findResponse.Endpoints.Count > 0)
{
foreach (XElement xElement in findResponse.Endpoints[0].Extensions)
{
Console.WriteLine("Printing Metadata from ServiceEndpoint:");
Console.WriteLine("Endpoint Information: " + xElement.Element("Information").Value);
Console.WriteLine("Endpoint Started at Time: " + xElement.Element("Time").Value);
Console.WriteLine();
}
}
Unfortunately this does not work. I get InvalidOperationException:
Attempted to get contract type for DataModel, but that type is
not a ServiceContract, nor does it inherit a ServiceContract.
If I am heading in the right direction I need a way to express the type for the service contract for the discovery. Too bad I am not sure that it will even work like the normal WCF Discovery...
Please share your ideas or even better - working solutions.
I think exception message is clear enough.
For service discovery You try to use type of your data model, while You must use type of your WCF service implementation - this is different things.
Basically DataServicesV3 service adapter uses your data model and exposes it as a WCF service with it's own service contract.
Look at DataServiceV3 type declaration see that it is implementing some interface, i just don't remember name, in this interface declaration you will find [ServiceContract] and [ServiceOperation] attributes. This is Your SERVICE CONTRACT for all ancestors of DataServiceV3. They use THE SAME contract. Here stands another problem I haven't managed to solve yet - how to make WS-Discovery work with DataServices if they share same contract. You'd better dig in this way.

WCF send and receive string?

im able to successfully use an MSDN example on sending a message to an MSMQ and reading it from a self hosted WCF service.
I am trying to use a simple string in a new project. I can send the string to the queue no problem but the WCF service hosted, faults.
After trying to figure out why, using the Microsoft Service Trace Viewer and enabling logging on the host, it says its a poison message!
but my contract defines MsmqMessage
This is what I am using to send:
System.Messaging.Message msg = new System.Messaging.Message(this.textBox1.Text);
And this is my contract (receiving):
[OperationContract(IsOneWay = true, Action = "*")] void
ProcessIncomingMessage(MsmqMessage<string> incomingMessage);
The content of the message when looking through MMC:
<?xml version="1.0"?>
<string>test</string>
any ideas?
Fixed: on the sender, define the formatter: msg.Formatter = new XmlMessageFormatter(new string[] { "System.String" }); on the contract, decorate it with a knowntype of string: [ServiceKnownType(typeof(String))]

WCF- Error handling when streaming

In order to support streaming i return Message with override to OnWriteBody...
The problem is if an exception is thrown in the OnWriteBody (DB timeout or whichever)
The ProvideFault in the IErrorHandler is not called and therefore i have no way to propagate the error to the client( via a filtering in the IErrorHandler).
Is there a way to solve this.
Thanks.
when doing streaming with WCF I create two ServiceContracts one that does the streaming another that will send the notification at the end of the streaming.
The response ServiceContract I use a duplex type binding. The client as to call the response ServiceContract first to get a ticket for its transaction then call my transfer ServiceContract. Then at the end of the transaction the client will get notified of success or failure from the response ServiceContract.
[ServiceContract]
public interface IStreamFileService
{
[OperationContract]
void Upload(Stream stream);
}
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ITransferCallback))]
public interface IStreamFileResponseService
{
[OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]
Guid StartUpload();
}
[ServiceContract]
public interface ITransferCallback
{
[OperationContract]
void OperationComplete(ResponseMessage response);
}
I do this in two services because my requirements and workflow requires me to track many things and do authentication, validation, etc.
OnWriteBody is called when response headers, like 200 was already sent to client. There for is impossible to handle errors in this stage.
Two workaround/tricks I've used:
Wait for first data-row before sending 200(like before returning Message) and iterate further rows inside OnWriteBody. This will work for because most of SQL Errors and Timeouts occurs before showing any data. Still, not cover cases when error appears while result-set iteration.
Have special error handling code on client and server. Like, in case of error server inside OnWriteBody may serialize error and send it as special Data-Row. Client should expect such special Data-Row while receiving response and handle accordingly.