I'm trying to do a full Angularjs web site for training. I've read many articles about this Method not allowed, but didn't find a solution. I'm trying to send a data object to my service.
Error : Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
Here is my AngularJS Part.
var addNews =
{
Title: newsList.newsTitle,
NewsContent: newsList.newsContent,
CreationDate: newsList.newsCreationDate,
CreatedBy: newsList.newsAuthor,
ModificationDate: newsList.newsCreationDate,
ModifiedBy: newsList.newsAuthor
};
var news = JSON.stringify(addNews);
$http({
method: 'POST',
dataType: 'json',
url: 'http://localhost:11672/InfinytecServices.svc/SaveNews',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
data: news
});
Here's my service part
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "/SaveNews",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
int SaveNews(News news);
WebConfig Comming
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1"/>
</system.web>
<system.serviceModel>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
<extensions>
<behaviorExtensions>
<add
name="crossOriginResourceSharingBehavior"
type="InfinytecWebService.CORSEnablingBehavior, InfinytecWebService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
<crossOriginResourceSharingBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehavior" name="InfinytecWebService.InfinytecServices">
<endpoint address=""
behaviorConfiguration="web"
binding="webHttpBinding"
contract="InfinytecWebService.IInfinytecServices" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
And at least , the CORS
public class CORSEnablingBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void AddBindingParameters(
ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters){ }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(
new CORSHeaderInjectingMessageInspector()
);
}
public void Validate(ServiceEndpoint endpoint) { }
public override Type BehaviorType { get { return typeof(CORSEnablingBehavior); } }
protected override object CreateBehavior() { return new CORSEnablingBehavior(); }
private class CORSHeaderInjectingMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(
ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
return null;
}
private static IDictionary<string, string> _headersToInject = new Dictionary<string, string>
{
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS" },
{ "Access-Control-Allow-Headers", "X-Requested-With,Content-Type" }
};
public void BeforeSendReply(ref Message reply, object correlationState)
{
var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
foreach (var item in _headersToInject)
httpHeader.Headers.Add(item.Key, item.Value);
}
}
}
Can you help me?
In advance, thanks! :)
Try one of the following
Define a another WebInvoke method with Method="OPTIONS" , the method should return empty content , since your CORS behavior handler adds all pre-flight headers needed for your browser .
Your CORS Extension should analyze the current request METHOD if it is OPTIONS it should short-circuit and return empty content with the pre-flight headers. If the method type is "GET"/"POST" it should let the request through to be processed by the endpoint.
The browser makes two request one to get pre-flight info using options and another for the actual api call .
the problem you are having is the first call by the browser Method=OPTIONS is being rejected by your endpoint. because it can only process POST.
Related
I have WCF service with DataContract json serialization. I would like to add service endpoints to consume Protobuf data messages.
I tried to use nugget package ProtoBuf.Services.WCF.
Added endpoint via web.config configuration. However, every request on protobuf endpoint with address "proto" returns 400 Bad request. Web.config sample is written bellow. Endpoint with default address "" works properly.
Get method:
HTTP 200 OK http://localhost:65460/BeaconService.svc/GetData
HTTP 400 BAD REQUEST: http://localhost:65460/BeaconService.svc/proto/GetData
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding transferMode="Streamed">
<security mode="None" />
</binding>
</webHttpBinding>
<basicHttpBinding>
<binding messageEncoding="Mtom">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<extensions>
<behaviorExtensions>
<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net" />
</behaviorExtensions>
</extensions>
<services>
<service behaviorConfiguration="DefaultServiceBehavior" name="Services.BeaconService">
<endpoint address="" behaviorConfiguration="httpBehavior" binding="webHttpBinding" contract="Services.IBeaconService" />
<endpoint address="proto" behaviorConfiguration="protoBehavior" binding="basicHttpBinding" contract="Services.IBeaconService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="protoBehavior">
<protobuf />
</behavior>
<behavior name="httpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</system.serviceModel>
Please, which part of configuration is defective. Eventualy, what is proper way to call Get method on "proto" WCF endpoint to avoid HTTP 400 Bad request message?
Unfortunately, I have failed to implement ProtoBuf.Services.WCF and decided to use another approach. In general, WCF by default uses DataContractSerializer.
After reading this article, I realized It is possible to replace this serializer with another one, f.e. protobuf serializer in this library. So I created behavior extension, which replaces DataContractSerializer with my custom ProtobufSerializer. In configuration added another endpoint, which has set behavior extension to use my custom ProtobufSerializer.
WebHttpBehavior:
public class ProtobufBehavior : WebHttpBehavior
{
protected override IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
return new ProtobufDispatchFormatter(operationDescription);
}
protected override IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
return new ProtobufDispatchFormatter(operationDescription);
}
}
Dispatch formatter:
namespace Services.Extension.ProtobufSerializationExtension
{
public class ProtobufDispatchFormatter : IDispatchMessageFormatter
{
OperationDescription operation;
bool isVoidInput;
bool isVoidOutput;
public ProtobufDispatchFormatter(OperationDescription operation)
{
this.operation = operation;
this.isVoidInput = operation.Messages[0].Body.Parts.Count == 0;
this.isVoidOutput = operation.Messages.Count == 1 || operation.Messages[1].Body.ReturnValue.Type == typeof(void);
}
public void DeserializeRequest(Message message, object[] parameters)
{
if (!message.IsEmpty)
{
XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
bodyReader.ReadStartElement("Binary");
byte[] rawBody = bodyReader.ReadContentAsBase64();
MemoryStream ms = new MemoryStream(rawBody);
using (StreamReader sr = new StreamReader(ms))
for (int i = 0; i < parameters.Length; i++)
parameters[i] = Serializer.Deserialize(operation.Messages[i].Body.Parts[i].Type, sr.BaseStream);
}
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
byte[] body;
using (MemoryStream ms = new MemoryStream())
using (StreamWriter sw = new StreamWriter(ms))
{
Serializer.Serialize(sw.BaseStream, result);
sw.Flush();
body = ms.ToArray();
}
Message replyMessage = Message.CreateMessage(messageVersion, operation.Messages[1].Action, new RawBodyWriter(body));
replyMessage.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw));
return replyMessage;
}
class RawBodyWriter : BodyWriter
{
internal static readonly byte[] EmptyByteArray = new byte[0];
byte[] content;
public RawBodyWriter(byte[] content)
: base(true)
{
this.content = content;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Binary");
writer.WriteBase64(content, 0, content.Length);
writer.WriteEndElement();
}
}
}
}
Extension element:
namespace Services.Extension.ProtobufSerializationExtension
{
public class ProtobufSerializationServiceElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(ProtobufBehavior); }
}
protected override object CreateBehavior()
{
return new ProtobufBehavior();
}
}
}
Web config:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding transferMode="Streamed">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<extensions>
<behaviorExtensions>
<add name="protobufExtension" type="Services.Extension.ProtobufSerializationExtension.ProtobufSerializationServiceElement, Services" />
</behaviorExtensions>
</extensions>
<services>
<service behaviorConfiguration="DefaultServiceBehavior" name="Services.BeaconService">
<endpoint address="" behaviorConfiguration="httpBehavior" binding="webHttpBinding" contract="Services.IBeaconService" />
<endpoint address="proto" behaviorConfiguration="protoBehavior" binding="webHttpBinding" contract="Services.IBeaconService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="protoBehavior">
<webHttp/>
<protobufExtension/>
</behavior>
<behavior name="httpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</system.serviceModel>
Services.Extension.ProtobufSerializationExtension is name of my custom namespace inside application structure. Hope this helps someone.
Please consider this code:
<system.web>
<compilation debug="true" targetFramework="4.6"/>
<httpRuntime targetFramework="4.5.2"/>
<authentication mode="None" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="MyNameSpace.Services.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint binding="basicHttpBinding" contract="MyNameSpace.Services.ISrv"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http"/>
</protocolMapping>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="AuthSecurity" type="MyNameSpace.CustomAuthorization" />
</modules>
<directoryBrowse enabled="true"/>
</system.webServer>
and the HttpModule code is:
namespace MyNameSpace
{
public class CustomAuthorization : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
CheckAccess();
}
private bool CheckAccess()
{
HttpContext c = HttpContext.Current;
if (HttpContext.Current.Handler != null) // <--Break Point
{
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
...
}
return false;
}
}
}
and in the client I wrote this code:
Service1client client = new Service1client();
client.ClientCredentials.UserName.UserName = "mmmm"
client.ClientCredentials.UserName.Password = "nnnn";
var tmp = client.DoWork(1);
the problem is after running the project, Service returns the correct result but HttpModule code didn't execute.
When I use a breakpoint in HttpModule it hits during Application_Start event. But after that it doesn't hit any more and its code doesn't execute.
Where is the problem?
Thanks
As I understand it, you defined just what to do at application start; if you want to check incoming requests, try to add these methods to your HttpModule and set breakpoints to check whether those methods are hit:
private void Application_BeginRequest(Object source,
EventArgs e)
{
CheckAccess();
}
private void Application_EndRequest(Object source, EventArgs e)
{
CheckAccess();
}
Of course you need to register those methods at application start:
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
i'm developing an small app, using a wcf service to provide data.
I want to add some headers to every message request, so i create an attribute inherit from IContractBehavior, then apply it to my service contract interface:
//SecuredServiceAttribute.cs
[AttributeUsage(AttributeTargets.Interface, Inherited = true)]
public class SecuredServiceAttribute : Attribute, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageInspector());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new ServerMessageInspector());
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
}
My ClientMessageInspector class as following:
// ClientMessageInspector.cs
public class ClientMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageHeader header = MessageHeader.CreateHeader("smheader", "ns", "smvalue");
request.Headers.Add(header);
return null;
}
}
and my ServerMessageInspector:
// ServerMessageInspector.cs
public class ServerMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
int found = request.Headers.FindHeader("smheader", "ns");
if (found != -1)
{
string header = request.Headers.GetHeader<string>("smheader", "ns");
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
Now i apply SecuredServiceAttribute to the contract
// IService1.cs
[ServiceContract]
[SecuredService]
public interface IService1
{
[OperationContract]
string GetData();
}
The problem is: i put some breakpoint at BeforeSendRequest and AfterReceiveRequest but just AfterReceiveRequest is hit up, so that request.Headers.FindHeader("smheader", "ns") always return -1 because the BeforeSendRequest is not run.
Here is my service model section at server side:
<system.serviceModel>
<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>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
and client side:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:59814/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1" contract="Service.IService1"
name="BasicHttpBinding_IService1" />
</client>
Could you help me find what's wrong in my code?
Sorry i'm not good at English.
I'm trying to send a JSON object to my webservice method, the method is defined like this:
public String SendTransaction(string trans)
{
var json_serializer = new JavaScriptSerializer();
Transaction transObj = json_serializer.Deserialize<Transaction>(trans);
return transObj.FileName;
}
Where I want to return the FileName of this JSON string that I got as a parameter.
The code for the android application:
HttpPost request = new HttpPost(
"http://10.118.18.88:8080/Service.svc/SendTransaction");
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
// Build JSON string
JSONStringer jsonString;
jsonString = new JSONStringer()
.object().key("imei").value("2323232323").key("filename")
.value("Finger.NST").endObject();
Log.i("JSON STRING: ", jsonString.toString());
StringEntity entity;
entity = new StringEntity(jsonString.toString(), "UTF-8");
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
"application/json"));
entity.setContentType("application/json");
request.setEntity(entity);
// Send request to WCF service
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity httpEntity = response.getEntity();
String xml = EntityUtils.toString(httpEntity);
Log.i("Response: ", xml);
Log.d("WebInvoke", "Status : " + response.getStatusLine());
I only get a long html file out, which tells me The server has encountered an error processing the request. And the status code is HTTP/1.1 400 Bad Request
My Transaction class is defined in C# like this:
[DataContract]
public class Transaction
{
[DataMember(Name ="imei")]
public string Imei { get; set; }
[DataMember (Name="filename")]
public string FileName { get; set; }
}
How can I accomplish this in the right way?
EDIT, this is my web.config
<?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>
<behaviors>
<endpointBehaviors>
<behavior name="httpBehavior">
<webHttp />
</behavior >
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<!-- 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>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<services>
<service name="Service.Service">
<endpoint address="" behaviorConfiguration="httpBehavior" binding="webHttpBinding" contract="Service.IService"/>
</service>
</services>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</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>
#Tobias, This is not an answer. But since it was a little bit long for comment, I post it here. Maybe it can help to diagnose your problem. [A full working code].
public void TestWCFService()
{
//Start Server
Task.Factory.StartNew(
(_) =>{
Uri baseAddress = new Uri("http://localhost:8080/Test");
WebServiceHost host = new WebServiceHost(typeof(TestService), baseAddress);
host.Open();
},null,TaskCreationOptions.LongRunning).Wait();
//Client
var jsonString = new JavaScriptSerializer().Serialize(new { xaction = new { Imei = "121212", FileName = "Finger.NST" } });
WebClient wc = new WebClient();
wc.Headers.Add("Content-Type", "application/json");
var result = wc.UploadString("http://localhost:8080/Test/Hello", jsonString);
}
[ServiceContract]
public class TestService
{
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
public User Hello(Transaction xaction)
{
return new User() { Id = 1, Name = "Joe", Xaction = xaction };
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public Transaction Xaction { get; set; }
}
public class Transaction
{
public string Imei { get; set; }
public string FileName { get; set; }
}
}
I've created a simple RESTful WCF file streaming service. When an error occurs, I would like a 500 Interal Server Error response code to be generated. Instead, only 400 Bad Requests are generated.
When the request is valid, I get the proper response (200 OK), but even if I throw an Exception I get a 400.
IFileService:
[ServiceContract]
public interface IFileService
{
[OperationContract]
[WebInvoke(Method = "GET",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/DownloadConfig")]
Stream Download();
}
FileService:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class GCConfigFileService : IGCConfigFileService
{
public Stream Download()
{
throw new Exception();
}
}
Web.Config
<location path="FileService.svc">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.serviceModel>
<client />
<behaviors>
<serviceBehaviors>
<behavior name="FileServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="FileService"
behaviorConfiguration="FileServiceBehavior">
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration="FileServiceBinding"
behaviorConfiguration="web"
contract="IFileService"></endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding
name="FileServiceBinding"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
transferMode="Streamed"
openTimeout="04:01:00"
receiveTimeout="04:10:00"
sendTimeout="04:01:00">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
SIMPLE:
Try out throw new WebFaultException(HttpStatusCode.InternalServerError);
To specify an error details:
throw new WebFaultException<string>("Custom Error Message!", HttpStatusCode.InternalServerError);
ADVANCED:
If you want better exception handling with defining HTTP status for each exception you'll need to create a custom ErrorHandler class for example:
class HttpErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (fault != null)
{
HttpResponseMessageProperty properties = new HttpResponseMessageProperty();
properties.StatusCode = HttpStatusCode.InternalServerError;
fault.Properties.Add(HttpResponseMessageProperty.Name, properties);
}
}
}
Then you need to create a service behaviour to attach to your service:
class ErrorBehaviorAttribute : Attribute, IServiceBehavior
{
Type errorHandlerType;
public ErrorBehaviorAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
Attaching to behaviour:
[ServiceContract]
public interface IService
{
[OperationContract(Action = "*", ReplyAction = "*")]
Message Action(Message m);
}
[ErrorBehavior(typeof(HttpErrorHandler))]
public class Service : IService
{
public Message Action(Message m)
{
throw new FaultException("!");
}
}