I'm creating a WCF Service, and it's working fine while I'm connecting it to a WinForms Client. But I want to access it throught the browser. Some methods are working fine, but when I'm trying to send back an object that includes multiples objects it returns the error message "A connection was reset"... I was trying to test my service with ARC and with JQuery Ajax, and all the cases I received the same error.
I almost forgot telling you, this issue only happens if I create a instance to Period attribute. If I return the object clear, I don't have any issue.
I share to you a test I made based on the original code. I hope you could help me.
WCF Service
using MercSoft.Conservatorio.DataModels;
using MercSoft.Conservatorio.Request;
using MercSoft.Conservatorio.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
namespace Mercsoft.Conserv.WSv2
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Conservatorio
{
// To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json)
// To create an operation that returns XML,
// add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
// and include the following line in the operation body:
// WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
[OperationContract(Name = "EstaActivo"), WebGet]
public bool isActive()
{
return false;
}
[OperationContract(Name="PruebaOro"), WebInvoke(Method="POST", ResponseFormat= WebMessageFormat.Json)]
public PreRegisterResponse pruebaOro(PreRegisterRequest request)
{
PreRegisterResponse response = new PreRegisterResponse();
response.Period = new ModulesDataModel();
return response;
}
// Add more operations here and mark them with [OperationContract]
}
}
PreRegister Response
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
using MercSoft.Conservatorio.DataModels;
using System.Runtime.Serialization;
using MercSoft.Conservatorio.Request;
namespace MercSoft.Conservatorio.Response
{
[DataContract]
public class PreRegisterResponse : BaseResponse
{
[DataMember]
public PreRegisterDataModel Period { get; set; }
public PreRegisterResponse()
: base()
{
}
}
}
PreRegisterDataModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace MercSoft.Conservatorio.DataModels
{
[DataContract(IsReference=true)]
public class SystemPeriodsDataModel
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int PeriodType { get; set; }
[DataMember]
public String PeriodTypeString { get; set; }
[DataMember]
public DateTime? StartDate { get; set; }
[DataMember]
public DateTime? EndDate { get; set; }
[DataMember]
public String DatePeriod { get; set; }
[DataMember]
public bool WithInstument { get; set; } //Pre-register ONLY
[DataMember]
public bool Active { get; set; }
}
}
WebConfig
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="Mercsoft.Conserv.WSv2.Conservatorio">
<endpoint address="" behaviorConfiguration="Mercsoft.Conserv.WSv2.ConservatorioAspNetAjaxBehavior"
binding="webHttpBinding" contract="Mercsoft.Conserv.WSv2.Conservatorio" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="Mercsoft.Conserv.WSv2.ConservatorioAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I just found the same issue with a piece of code in a WCF service I'm working on, that is (now) using the webHttpBinding (for REST clients). The culprit was the property "IsReference=true" in a DataContract class. I needed that flag set to TRUE because the graph of objects contains circular references; this way the returned response has a lot less bytes than if the real objects were serialized.
I don't know why this works with SOAP and other bindings but not with webHttpBinding, but since I needed to add REST support, the service stopped working when a DataContract class with IsReference=true was being returned.
My temporary solution was to create another class with the same properties as the original, but without the IsReference property. I need to investigate this further but in the meantime I hope this helps.
Related
I'm having trouble with Team Foundation Server 2015 Web Hooks (https://www.visualstudio.com/get-started/webhooks-and-vso-vs)
I can create web hook on TFS side and it successfully uses RequestBin WebService. But when I create the WCF Web service - have errors all the time.
First of all I get #Cannot process the message because the content type 'application/json; charset utf-8' was not the expected type 'text/xml;charset utf-8'.(415)"
I've read a lot of articles and related questions here.
Tried to add Factory="System.ServiceModel.Activation.WebServiceHostFactory" to .svc file. After it I've got 404 error while consuming service and no endpoint found while trying to open it's WSDL
So, my Interface is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace MyService
{
// ПРИМЕЧАНИЕ. Команду "Переименовать" в меню "Рефакторинг" можно использовать для одновременного изменения имени интерфейса "IService1" в коде и файле конфигурации.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke]
string RollUp(string sData);
// TODO: Добавьте здесь операции служб
}
// Используйте контракт данных, как показано в примере ниже, чтобы добавить составные типы к операциям служб.
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
My program is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace MyService
{
// ПРИМЕЧАНИЕ. Команду "Переименовать" в меню "Рефакторинг" можно использовать для одновременного изменения имени класса "Service1" в коде, SVC-файле и файле конфигурации.
// ПРИМЕЧАНИЕ. Чтобы запустить клиент проверки WCF для тестирования службы, выберите элементы Service1.svc или Service1.svc.cs в обозревателе решений и начните отладку.
public class Service1 : IService1
{
public string RollUp(string sData)
{
return "Sucess " + sData;
}
}
}
my web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!--Чтобы избежать раскрытия метаданных, до развертывания задайте следующим параметрам значение "false". -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- Чтобы при сбое получать подробные сведения об исключении для целей отладки, установите для нижеприведенного параметра значение true. Перед развертыванием установите значение false, чтобы избежать раскрытия информации об исключении -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="json">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="MyService.Service1">
<endpoint name="jsonEP"
address=""
binding="webHttpBinding"
behaviorConfiguration="json"
contract="MyService.IService1"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
Для просмотра корневого каталога веб-приложения во время отладки установите значение true.
Перед развертыванием установите значение false, чтобы избежать раскрытия сведений в папке веб-приложения.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
And with all of this I get 404 error.
Hope someone can help me as I can't beat this web services for days and for now have no idea what to do.
Kindly, i made a simple WCF self console hosted service with the following code:
using System.ServiceModel;
namespace SimpleService
{
[ServiceContract]
public interface ISimpleService
{
[OperationContract]
int IncrementNumber();
}
}
And the implementation :
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;
namespace SimpleService
{
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
public class SimpleService : ISimpleService
{
int _number;
public int IncrementNumber()
{
_number = _number + 1;
Thread.Sleep(100);
Console.WriteLine(_number.ToString());
return _number;
}
}
}
And I hosted in app with the following code :
using System;
using System.ServiceModel;
namespace Host
{
class Program
{
public static void Main()
{
using (ServiceHost host = new
ServiceHost(typeof(SimpleService.SimpleService)))
{
host.Open();
Console.WriteLine("Host started # " + DateTime.Now.ToString());
Console.ReadLine();
}
}
}
}
And app config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="mexBehavior" name="SimpleService.SimpleService">
<endpoint address="SimpleService" binding="basicHttpBinding"
contract="SimpleService.ISimpleService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
And now iam trying to call this service from Android mobile app that will call this service hopfully using SOAP Message through this address( http://amyamyamy.no-ip.org/ )
but i couldnt make it work till now!!!
so i need your help regarding c# code that can call the above hosted service using SOAP message.
Many thanks for your kind effort.
My Client app code is :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using System.Xml;
namespace Client
{
class Program
{
public static void Main()
{
//SimpleService.SimpleServiceClient client =
//new SimpleService.SimpleServiceClient();
var client = new WebClient();
string data = GetSoap();
Console.WriteLine(data);
client.Headers.Add("Content-Type", "text/xml;charset=utf-8");
client.Headers.Add("SOAPAction", "\"http://tempuri.org/IService1/GetData\"");
var response = client.UploadString("http://amyamyamy.no-ip.org/SimpleService/SimpleService.svc", data);
Console.WriteLine("Number after first call = " +response.ToString());
Console.ReadLine();
}
static string GetSoap()
{
string xmlPayloadText = #"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/"">
<soapenv:Header/>
<soapenv:Body>
<tem:GetData>
<!--Optional:-->
<tem:value></tem:value>
</tem:GetData>
</soapenv:Body>
</soapenv:Envelope>";
return xmlPayloadText;
}
}
}
With 404 it means it giving you a service not found error and to my understanding that's because the <baseAddresses> part in your service configuration file
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080" />
</baseAddresses>
</host>
You are actually using localhost wheras you should be using a proper server name or IP address.
Again, in your client application you are trying to get the service metadata WSDL using
http://amyamyamy.no-ip.org/SimpleService/SimpleService.svc
Which to me looks like, as if your service is deployed in IIS server but it's not and so you are not able to access the service.
You should rather change your base address like
<host>
<baseAddresses>
<add baseAddress="http://my_actual_server_name:8080/" />
</baseAddresses>
</host>
In your client application try accessing it like
http://my_actual_server_name:8080/SimpleService
That is, your client code
var response = client.UploadString("http://my_actual_server_name:8080/SimpleService", data);
I'm getting the fabled Error: Cannot obtain Metadata from... message, particularly http://localhost:1640/Service1.svc I've scoured stackoverflow and Google and, so far, none of it has helped. I created a new product to dumb it down and it's still not working. So I am here asking for help.
I'm trying to setup a WCF Service that uses JSON, which means I need to use webhttpbinding, in C#. When I use the WCF Test Client, I get the aforementioned metadata error. I'm using Visual Studio Express 2010 and the target framework. I've been at this for two days and cannot understand why or what is the problem.
I would appreciate any help. Thank you.
Here is my web.config file:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfService4.Service1"
behaviorConfiguration="jsonRestDefault">
<endpoint
name="jsonRestEndpoint"
behaviorConfiguration="RESTFriendly"
binding="webHttpBinding"
contract="IService1"
address="http://localhost:1640/Service1.svc"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="jsonRestDefault">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RESTFriendly">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Here is the IService1.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService4
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(
Method = "GET",
UriTemplate = "players",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
List<Person> GetPlayers();
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class Person
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public int Age { get; set; }
public Person(string firstName, string lastName, int age)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
}
}
}
Here is the Service1.svc.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Net;
namespace WcfService4
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
public class Service1 : IService1
{
public List<Person> GetPlayers()
{
List<Person> players = new List<Person>();
players.Add(new Person ( "Peyton", "Manning", 35 ) );
players.Add(new Person ( "Drew", "Brees", 31 ) );
players.Add(new Person ( "Brett", "Favre", 38 ) );
return players;
}
}
}
Take a look at this link
It states the following:
WebHttpBinding is a REST-based binding - REST does not expose
metadata like WSDL/XSD contrary to SOAP.
In addition to bruno bologna's answer and link, the link at WCF REST Service not visible in WCFTestClient also provides some very useful information. Basically, the reason why it's not working is the WCFTestClient is not designed for web (think JSON). It hooks in through SOAP. If I have a service that is dependent on JSON, I cannot test it through the WCFTestClient.
I see that it is possible to modify the client configuration file in WCFTestClient to enable web binding, but that may be because of future-proofing for WADL or if someone writes a WADL service extension. That's just specultation on my part, though. Otherwise, it doesn't appear one can test WCF Service with JSON using the WCFTestClient tool.
I am trying to create a WCF Restful Service.
Here is my contract: (The ActivateUser class extends the BaseResult class).
namespace SmartShopServerContract {
[ServiceContract]
public interface IService {
[OperationContract]
[WebGet(RequestFormat=WebMessageFormat.Json, ResponseFormat=WebMessageFormat.Json, UriTemplate="au/{eMail}/{password}/{idHandy}")]
ActivateUserResult ActivateUser(string eMail, string password, string idHandy);
}
// Basisklasse der Resultate --> alle Resultate haben einen definierten Status!
[DataContract]
public abstract class BaseResult {
private string status;
public BaseResult(string status) {
this.status = status;
}
[DataMember]
public string Status {
get { return this.status; }
}
}
// Result für ActivateUser
[DataContract]
public class ActivateUserResult : BaseResult {
public ActivateUserResult(string status)
: base(status) {
}
[DataMember]
public string CryptedPassword { get; set; }
}
}
Here is the implementation of the Service:
namespace SmartShopServerService {
public class ServiceSmartShop : IService {
public ActivateUserResult ActivateUser(string eMail, string password, string idHandy) {
return new ActivateUserResult("OK") {
CryptedPassword="testatsa"
};
}
And there is the Web.config file:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json">
</standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
<services>
<service name="SmartShopServerService.ServiceSmartShop" behaviorConfiguration="RESTBehavior">
<endpoint address="/" binding="webHttpBinding" contract="SmartShopServerContract.IService" behaviorConfiguration="SmartShopBehavior"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="RESTBehavior">
<serviceMetadata httpGetEnabled="true" policyVersion="Policy15"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SmartShopBehavior">
<webHttp automaticFormatSelectionEnabled="false"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.5" sku=".NETFramework,Version=v4.5"/>
</startup>
<system.web>
<compilation debug="true"/>
</system.web>
<system.webServer>
<modules>
<remove name="WebDAVModule"/>
</modules>
</system.webServer>
</configuration>
I am testing this with the "VS2012 native tool commant prompt" like this:
svcutil.exe http://localhost:51162/SmartShopService.svc/au/data1/data2/data3
The code is being executed, but I am still getting a Method not allowed (405) exception.
Any thoughts on that?
--> currently local use
--> IIS Express (Visual Studio 2012)
You're using svcutil to create a proxy for a "RESTful WCF service". This does not work. The quick reason is that Web endpoints do not expose metadata for the svcutil tool to know what requests it needs to send to it. The long version is on the linked blog post.
The problem was the base class (BaseResult) for the ActivateUser class --> BaseResult
It seems like that it is not possible to extend a DataContract class and expect it to work.
Now i am using a Interface instead of a base class
public interface IResult {
string Status{get;set;}
}
[DataContract]
public class ActivateUserResult : IResult {
[DataMember]
public string CryptedPassword { get; set; }
[DataMember]
public string Status { get; set; }
}
This is working....thats all i know ;)
I seem to be having a problem for getting IErrorHandler interface to work. My code is
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace WcfService3
{
public class Service1 : IService1
{
public string GetData(int value)
{
throw new Exception("asdf");
}
}
public class MyErrorHandler : IErrorHandler
{
public MyErrorHandler()
{
string Hello = "";
}
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
var vfc = new MyFault();
var fe = new FaultException<MyFault>(vfc);
var fault = fe.CreateMessageFault();
msg = Message.CreateMessage(version, fault, "http://ns");
}
}
public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior
{
public override Type BehaviorType
{
get { return GetType(); }
}
protected override object CreateBehavior()
{
return this;
}
private IErrorHandler GetInstance()
{
return new MyErrorHandler();
}
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandlerInstance = GetInstance();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(errorHandlerInstance);
}
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
{
if (endpoint.Contract.Name.Equals("IMetadataExchange") &&
endpoint.Contract.Namespace.Equals("http://schemas.microsoft.com/2006/04/mex"))
continue;
foreach (OperationDescription description in endpoint.Contract.Operations)
{
if (description.Faults.Count == 0)
{
throw new InvalidOperationException("FaultContractAttribute not found on this method");
}
}
}
}
}
}
My web.config is:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="WcfService3.Service1">
<endpoint address=""
binding="basicHttpBinding"
contract="WcfService3.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="errorHandler"
type="WcfService3.ErrorHandlerExtension, WcfService3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
My WCF interface is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService3
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(MyFault))]
string GetData(int value);
}
[DataContract]
public class MyFault
{
}
}
My question is in IErrorHandler in WCF, if there is any exception during the WCF service call, the HandlerError() function is suppose to get called first like the C# windows application UnhandledException class and then the service should crash right? In the code above, during the service call, an exception is thrown but my HandlerError function is not getting called before the exception is thrown? My goal is to log the error and the WCF service can throw the unhandled exception and crash. I was expecting during the debugging that the breakpoint will visit the HandleError function, but that function is not getting called and just an exception shows up?
Aren't you missing <errorHandler /> in your behavior section?
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<!-- HERE -->
<errorHandler />
<!-- HERE -->
</behavior>
The full answer is here. Plus 1 to that answer.
In case anyone else comes across this, when I ran across this error, it was because the error was getting thrown in a method that was called from some LINQ expression. The method wasn't actually called until WCF tried to serialize the response, which then threw outside of the service scope. WCF won't pass these errors to the IErrorHandler.
Materializing the list before returning using .ToList() solved this problem for me.