H.Kai H.Kai - 1 month ago 28
C# Question

WCF POST method get error 400 Bad Request

I am using WCF POST method, once i added parameter POST to the service its return error 400 Bad Request, if i left the parameter empty it can access to my service.

This is my Interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
using System.IO;
namespace SampleArticle
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IRestService" in both code and config file together.
[ServiceContract(Namespace="IRestService/JSONData")]
public interface IRestService
{

[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,UriTemplate = "authorize")]
Stream authorize(Stream streamdata);

}
}


This is 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.0" />

</system.web>

<system.serviceModel>


<services>
<service name="SampleArticle.RestService" behaviorConfiguration="serviceBehavior">
<endpoint address="" binding="webHttpBinding" contract="SampleArticle.IRestService" behaviorConfiguration="web"></endpoint>
</service>
</services>

<behaviors>
<serviceBehaviors>

<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>

</serviceBehaviors>

<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>

</behaviors>

<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>


<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>


<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />

</system.webServer>

</configuration>


Im using Msxml2.ServerXMLHTTP to POST

Dim objXmlHttpMain , URL

URL="http://localhost/SampleArticle/RestService.svc/authorize"

strJSONToSend = "{""acctId"": ""Test10001"","
strJSONToSend = strJSONToSend & """language"": 200,"
strJSONToSend = strJSONToSend & """Code"": ""Test"","
strJSONToSend = strJSONToSend & """token"": ""abcd123412341234"","
strJSONToSend = strJSONToSend & """serialNo"": ""20161020160455982841""}"

// if i set the parameter to empty i can access to the service
'strJSONToSend = ""
Set objXmlHttpMain = CreateObject("Msxml2.ServerXMLHTTP")
'on error resume next
objXmlHttpMain.open "POST",URL, False

// if i change the "application/json" to "application/x-www-form-urlencoded" it works
'objXmlHttpMain.setRequestHeader "Content-Type", "application/json"
objXmlHttpMain.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"

objXmlHttpMain.send strJSONToSend


//check for output
S = objXmlHttpMain.responseText
response.write S

set objJSONDoc = nothing
set objResult = nothing


Server log msg


Incoming message for operation 'authorize' (contract 'IRestService' with namespace 'IRestService/JSONData') contains an unrecognized http body format value 'Json'. The expected body format value is 'Raw'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.


if i change the Content-Type "application/json" to "application/x-www-form-urlencoded"
it works , but i need the data in JSON format.
Is there any setting i am missing with ? Please advice.

Answer

I have solved my question my adding the custom WebContentTypeMapper. Here are my sample coding :

Create new class to allow receive the data as RAW type

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace SampleArticle
{
    public class MyWebContentTypeMapper : WebContentTypeMapper
    {
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
        {

            return WebContentFormat.Raw;
        }
    }
}

Web.Config add custom binding to the service

<system.serviceModel>
    <services>
        <service name="SampleArticle.RestService" behaviorConfiguration="serviceBehavior">
            <endpoint address="" binding="customBinding" bindingConfiguration="RawReceiveCapable" contract="SampleArticle.IRestService" behaviorConfiguration="web"></endpoint>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="serviceBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
            <behavior name="">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="web">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
    </behaviors>


    <bindings>
        <customBinding>
            <binding name="RawReceiveCapable">
                <webMessageEncoding webContentTypeMapperType="SampleArticle.MyWebContentTypeMapper, SampleArticle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
                <httpTransport manualAddressing="true" maxReceivedMessageSize="524288000" transferMode="Streamed"/>
            </binding>
        </customBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>

This Solved my issue , hope its help other too. Thank for helping