WebApi Put "Словарь параметров содержит пустую запись для параметра ..." - PullRequest
6 голосов
/ 08 марта 2012
public class ContactsController : ApiController
{
    private static readonly List<Contact> _contacts = new List<Contact>();
    public Contact PutContacts(int id, Contact contact)
    {
        if (_contacts.Any(c => c.Id == contact.Id) == false)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        contact.LastModified = DateTime.Now;
        return contact;
    }
}

http put header:

PUT /api/contacts/3 HTTP/1.1
User-Agent: Fiddler
Content-Type: application/json
Host: localhost:8080

тело:

{"Id":3,"Name":"mmm","Phone":"000 000 0000","Email":"mmm@gmail.com","LastModified":"2012-03-08T23:42:13.8681395+08:00"}

ответ:

HTTP/1.1 400 Bad Request
"The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'SelfHost.Contact PutContacts(Int32, SelfHost.Contact)' in 'SelfHost.ContactsController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."

Почему?спасибо.

PS:

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

Ответы [ 3 ]

2 голосов
/ 03 апреля 2012

У меня такая же проблема. Параметр запроса «id» равен нулю, а объект «contact» заполнен. Я думаю, что это проблема привязки модели. Если вы поставили точку останова в контроллере, посмотрите на это выражение:

this.ControllerContext.RouteData.Values["id"]

Вы увидите, что значение есть в данных маршрута; это просто не устанавливается на модели. У меня есть ActionFilter, и если я также добавлю точку останова, я вижу, что ActionArgument для actionContext имеет ключ для него, но значение NULL.

Я все еще исследую ...

1 голос
/ 08 марта 2012

Я не могу воспроизвести проблему, которую вы описываете.

Модель:

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public DateTime LastModified { get; set; }
}

Контроллер:

public class ContactsController : ApiController
{
    public Contact Put(int id, Contact contact)
    {
        return contact;
    }
}

Клиент:

class Program
{
    static void Main()
    {
        using (var client = new WebClient())
        {
            client.Headers[HttpRequestHeader.ContentType] = "application/json";
            var data = Encoding.UTF8.GetBytes(@"{""Id"":3,""Name"":""mmm"",""Phone"":""000 000 0000"",""Email"":""mmm@gmail.com"",""LastModified"":""2012-03-08T23:42:13.8681395+08:00""}");
            var result = client.UploadData("http://localhost:1405/api/contacts/4", "PUT", data);
            Console.WriteLine(Encoding.UTF8.GetString(result));
        }
    }
}

Когда я запускаю клиент, отправляется следующий запрос:

PUT /api/contacts/4 HTTP/1.1
Content-Type: application/json
Host: localhost:1405
Content-Length: 119
Expect: 100-continue
Connection: Keep-Alive

{"Id":3,"Name":"mmm","Phone":"000 000 0000","Email":"mmm@gmail.com","LastModified":"2012-03-08T23:42:13.8681395+08:00"}

и я получаю правильный результат с сервера. Поэтому я предполагаю, что отображаемый вами запрос не является фактическим запросом, отправляемым на сервер.

0 голосов
/ 05 мая 2012

craigtadlock, спасибо за вашу помощь и отправку сообщения об ошибке в Microsoft.У меня была такая же проблема с PUT.Никто из них не работал.В качестве обходного пути я взломал POST для обработки PUT.Если объект, который я отправляю на сервер, уже имеет свой идентификатор, POST-код обрабатывает его как PUT с этим идентификатором.Псевдокод:

public HttpResponseMessage<MyClass> PostMyClass(MyClass myObject)
{
    if( myObject.ID != 0 ){
         //do PUT code
    }else{
         //do POST code
    }
}
...