POST для WCF из Fiddler успешно, но передает нулевые значения - PullRequest
3 голосов
/ 11 ноября 2011

Я следил за этой серией видео на WCF и у меня работает демо.Он включает создание службы WCF, которая управляет формами оценки учащихся и реализует операции CRUD для работы со списком этих оценок.Я немного изменил свой код в соответствии с этим руководством , чтобы он возвращал результаты JSON в запрос браузера или Fiddler.Моя цель - выяснить, как использовать службу, создав собственные запросы в Fiddler, а затем использовать этот формат для использования службы из приложения на мобильном устройстве.

У меня проблемы с использованием SubmitEval метод (сохранить оценку) от Fiddler.Вызов работает, но все поля Eval имеют значение null (или значение по умолчанию), кроме Id, которое устанавливается в самой службе.

Вот мое объявление Eval (с использованием свойств вместо полей)согласно этот вопрос ):

[DataContract]
public class Eval //Models an evaluation
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Submitter { get; set; }

    [DataMember]
    public string Comment { get; set; }

    [DataMember]
    public DateTime TimeSubmitted { get; set; }
}

А вот соответствующая часть IEvalService:

[ServiceContract]
public interface IEvalService
{
 ...
   [OperationContract]
    [WebInvoke(RequestFormat=WebMessageFormat.Json,
       ResponseFormat=WebMessageFormat.Json, UriTemplate = "eval")]
    void SubmitEval(Eval eval);
}

И EvalService:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
class EvalService : IEvalService
{
...
  public void SubmitEval(Eval eval)
    {
        eval.Id = Guid.NewGuid().ToString();
        Console.WriteLine("Received eval");
        evals.Add(eval);
    }
}

В построителе запросов Fiddler я установил метод на POST, а адрес на http://localhost:49444/EvalServiceSite/Eval.svc/eval.Я добавил заголовок Content-Type: application/json; charset=utf-8 к заголовкам по умолчанию.Тело запроса:

{"eval":{"Comment":"testComment222","Id":"doesntMatter", 
  "Submitter":"Tom","TimeSubmitted":"11/10/2011 4:00 PM"}}

Ответ, который я получаю от отправки этого запроса, 200, но когда я смотрю на сохраненные Evals, только что добавленное мной действительное значение имеет Id, но Comment и Submitter равны нулю, а TimeSubmitted равно 1/1/0001 12:00:00 AM.

Похоже, что WCF получает запрос, но неправильно десериализует объект.Но если это так, я не знаю, почему это не вызывает каких-то исключений.Похоже, я делаю это правильно, или я что-то упустил?

ОБНОВЛЕНИЕ: Вот объявление конечной точки в App.config:

 <endpoint binding="webHttpBinding" behaviorConfiguration="webHttp"
   contract="EvalServiceLibrary.IEvalService" />

И поведение конечной точки, на которое ссылаются:

<behavior name="webHttp">
  <webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>

Ответы [ 2 ]

6 голосов
/ 11 ноября 2011

Стиль тела по умолчанию в атрибуте WebInvoke - Bare, что означает, что объект следует отправлять без оболочки, содержащей имя объекта:

{"Comment":"testComment222",
 "Id":"doesntMatter",
 "Submitter":"Tom",
 "TimeSubmitted":"11/10/2011 4:00 PM"}

Или вы можете установить стиль тела запроса на Wrapped, и это потребует ввода {"eval"...} объекта:

[OperationContract]
[WebInvoke(RequestFormat=WebMessageFormat.Json,
   ResponseFormat=WebMessageFormat.Json,
   UriTemplate = "eval",
   BodyStyle = WebMessageBodyStyle.WrappedRequest)] // or .Wrapped
void SubmitEval(Eval eval);

Обновление : в вашем коде есть другая проблема, так как вы используете DateTime, а формат, ожидаемый сериализатором WCF для дат в JSON, похож на \/Date(1234567890)\/. Вы можете изменить свой класс для поддержки имеющегося у вас формата, следуя логике, описанной в MSDN Link (детальный контроль формата сериализации для примитивов) и показанной в приведенном ниже коде.

public class StackOverflow_8086483
{
    [DataContract]
    public class Eval //Models an evaluation
    {
        [DataMember]
        public string Id { get; set; }

        [DataMember]
        public string Submitter { get; set; }

        [DataMember]
        public string Comment { get; set; }

        [DataMember(Name = "TimeSubmitted")]
        private string timeSubmitted;

        public DateTime TimeSubmitted { get; set; }

        public override string ToString()
        {
            return string.Format("Eval[Id={0},Submitter={1},Comment={2},TimeSubmitted={3}]", Id, Submitter, Comment, TimeSubmitted);
        }

        [OnSerializing]
        void OnSerializing(StreamingContext context)
        {
            this.timeSubmitted = this.TimeSubmitted.ToString("MM/dd/yyyy h:mm tt", CultureInfo.InvariantCulture);
        }

        [OnDeserialized]
        void OnDeserialized(StreamingContext context)
        {
            DateTime value;
            if (DateTime.TryParseExact(this.timeSubmitted, "MM/dd/yyyy h:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out value))
            {
                this.TimeSubmitted = value;
            }
        }
    }

    [ServiceContract]
    public interface IEvalService
    {
        [OperationContract]
        [WebInvoke(RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json, UriTemplate = "eval",
           BodyStyle = WebMessageBodyStyle.Wrapped)]
        void SubmitEval(Eval eval);
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    class EvalService : IEvalService
    {
        public void SubmitEval(Eval eval)
        {
            Console.WriteLine("Received eval: {0}", eval);
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(EvalService), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        string data = "{\"eval\":{\"Comment\":\"testComment222\",\"Id\":\"doesntMatter\", \"Submitter\":\"Tom\",\"TimeSubmitted\":\"11/10/2011 4:00 PM\"}}";
        WebClient c = new WebClient();
        c.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
        c.UploadData(baseAddress + "/eval", Encoding.UTF8.GetBytes(data));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
0 голосов
/ 09 июня 2017

Для POST вам нужно использовать BodyStyle = WebMessageBodyStyle.Bare NOT
WebMessageBodyStyle.Wrapped

    [OperationContract]
    [WebInvoke(RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json,UriTemplate = "eval",BodyStyle = WebMessageBodyStyle.Bare)]
    void SubmitEval(Eval eval);
...