Служба JSON WCF возвращает XML при ошибке - PullRequest
11 голосов
/ 22 июня 2011

Я запускаю ServiceHost для тестирования одного из моих сервисов, и все работает нормально, пока я не сгенерирую FaultException - взрыв Я получаю XML не JSON

мой контракт на обслуживание - прекрасный

   /// <summary>
    ///   <para>Get category by id</para>
    /// </summary>
    [OperationContract(AsyncPattern = true)]
    [FaultContract(typeof(CategoryNotFound))]
    [FaultContract(typeof(UnexpectedExceptionDetail))]
    IAsyncResult BeginCategoryById(
        CategoryByIdRequest request,
        AsyncCallback callback, object state);

    CategoryByIdResponse EndCategoryById(IAsyncResult result);

Host Set-up - scrummy yum

var host = new ServiceHost(serviceType, new Uri(serviceUrl));
host.AddServiceEndpoint(
    serviceContract,
    new WebHttpBinding(), "")
        .Behaviors.Add(
             new WebHttpBehavior
                            {
                                DefaultBodyStyle = WebMessageBodyStyle.Bare,
                                DefaultOutgoingResponseFormat = WebMessageFormat.Json,
                                FaultExceptionEnabled = true
                            });

host.Open();

Вот вызов - oo боль в животе

var request = WebRequest.Create(serviceUrl + "/" + serviceName);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.ContentLength = 0;

try
{
    // receive response
    using (var response = request.GetResponse())
    {
        var responseStream = response.GetResponseStream();

        // convert back into referenced object for verification
        var deserialiser = new DataContractJsonSerializer(typeof (TResponseData));
        return (TResponseData) deserialiser.ReadObject(responseStream);
    }
}
catch (WebException wex)
{
    var response = wex.Response;

    using (var responseStream = response.GetResponseStream())
    {
        // convert back into fault
        //var deserialiser = new DataContractJsonSerializer(typeof(FaultException<CategoryNotFound>));
        //var fex = (FaultException<CategoryNotFound>)deserialiser.ReadObject(responseStream);

        var text = new StreamReader(responseStream).ReadToEnd();
        var fex = new Exception(text, wex);    

        Logger.Error(fex);
        throw fex;
    }
}

текст var содержит правильную ошибку, но сериализован как Xml Что я здесь сделал неправильно

Ответы [ 6 ]

3 голосов
/ 27 июля 2011

Ответ заключается в реализации IErrorHandler и поддерживающего поведения

Я нашел этот отличный пост от iainjmitchell

http://iainjmitchell.com/blog/?p=142

2 голосов
/ 26 июля 2011

Я могу с радостью представить решение. У меня была точно такая же проблема, и после того, как я немного испортил свою конфигурацию поведения конечной точки, я обнаружил необходимый элемент конфигурации. Решение состоит в том, чтобы заставить wcf использовать выбранный формат (json):

 <behavior name="ExtendedJSONBehavior">
     <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="false"/>
 </behavior>

Как видите, ключом был атрибут "automaticFormatSelectionEnabled".

Веселись снова с wcf

0 голосов
/ 20 декабря 2013
//由于调用 ProvideFault 时,客户端处于阻塞状态,不要在这里进行长时间的操作
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
    //避免敏感信息泄漏,例如:数据库配置, error包含的错误信息应该记录到服务器的日志中,不能显示给客户端
    // FaultException<int> e = new FaultException<int>(123, error.Message);
    DateTime now = DateTime.Now;
    time = now.ToString("yyyyMMddHHmmssfff", DateTimeFormatInfo.InvariantInfo);// "" + now.Year.ToString() + now.Month.ToString() + now.Day.ToString() + now.Hour.ToString() + now.Minute.ToString() + now.Second.ToString() + now.Millisecond.ToString();
    string errorMsg = "服务内部错误_" + time;
    // FaultException fe = new FaultException(errorMsg);
    // MessageFault mf = fe.CreateMessageFault();
    // msg = Message.CreateMessage(version, mf, fe.Action);

    //The fault to be returned
    msg = Message.CreateMessage(version, "", errorMsg, new DataContractJsonSerializer(typeof(string)));

    // tell WCF to use JSON encoding rather than default XML
    WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);

    // Add the formatter to the fault
    msg.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

    //Modify response
    HttpResponseMessageProperty rmp = new HttpResponseMessageProperty();

    // return custom error code, 400.
    rmp.StatusCode = System.Net.HttpStatusCode.InternalServerError;
    rmp.StatusDescription = "Bad request";

    //Mark the jsonerror and json content
    rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
    rmp.Headers["jsonerror"] = "true";

    //Add to fault
    msg.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}
0 голосов
/ 30 июня 2011

Я не понимаю, почему вы используете WebRequest для звонков в службу WCF.Есть ли конкретная причина для этого?Как вы узнаете, когда вы обрабатываете WebException, что это будет FaultException<CategoryNotFound>?
Если вы используете прокси-сервер службы и ваша служба выдает FaultException<T>, вероятно, лучше написать ваш try-catch следующим образом:

try
{
    //Do service call
} 
catch (FaultException<CategoryNotFound> fe)
{
    //handle CategoryNotFound
}
catch (FaultException<UnexpectedExceptionDetail> fe)
{
    //handle UnexpectedExceptionDetail
}
catch (FaultException exc)
{
    //stuf
}
catch(Exception general){
    //all other stuff that might blow up
}
0 голосов
/ 22 июня 2011

В соответствии с документацией MSDN для DataContractJsonSerializer :

"Если во время сериализации исходящего ответа на сервере возникает ошибка или операция ответа вызывает исключение по какой-то другой причине, онане может быть возвращено клиенту как ошибка. "

Кроме того, это всего лишь предположение, но похоже, что этот сериализатор сериализуется в XML, а затем преобразует его в JSON.Итак, когда происходит ваша ошибка, она прерывается в середине процесса?С другой стороны, я могу быть совершенно неправ.

Удачи.

0 голосов
/ 22 июня 2011

Это, вероятно, не даст вам часть "почему". Взгляните на этот вопрос . Это позволяет вам захватывать и переформатировать ошибки, прежде чем они появятся в ответ. Это будет, по крайней мере, Json-ize ваши ответы достаточно, чтобы вы начали. этот также имеет аналогичную идею.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...