2011-02-08 3 views
4

Предположим, у меня есть контроллер, который обрабатывает сценарий CRUD для «дома». Get будет выглядеть примерно так:RESTful контроллеры с различными методами Http, но те же параметры

[HttpGet] 
    public ActionResult Index(int? homeId) 
    { 
     Home home = homeRepo.GetHome(homeId.Value); 

     return Json(home, JsonRequestBehavior.AllowGet); 
    } 

Пока все хорошо. Затем я добавляю сообщение для добавления новых.

[HttpPost] 
    public ActionResult Index(Home home) 
    { 
     //add the new home to the db 

     return Json(new { success = true }); 
    } 

Awesome. Но когда я использую ту же схему для обработки пут (обновление существующего дома) ...

[HttpPut] 
    public ActionResult Index(Home home) 
    { 
     //update existing home in the db 

     return Json(new { success = true }); 
    } 

Мы столкнулись с проблемой. Подписи метода для Post и Put идентичны, что, конечно, C# не нравится. Я мог бы попробовать несколько вещей, например добавить фиктивные параметры в подпись или изменить имена методов, чтобы напрямую отражать CRUD. Тем не менее, это хаки или нежелательны.

Что лучше всего подходит для сохранения RESTful, CRUD-контроллеров стиля здесь?

+0

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

+0

Поскольку подход RESTful требует, чтобы все они решались на один и тот же URL-адрес, просто с различными HttpMethods (Create = Post, Read = Get, Update = Put, Delete = Delete). Есть много причин для этого, но в основном это сделает javascript api, который я построю поверх этого, намного проще писать. Меньше, тоже. – Dusda

+1

Правильно, тогда решение Мэтта отлично работает. Сохраняет ваш внешний api RESTful, сохраняя при этом компиляцию кода на C#. –

ответ

12

Это лучшее решение, которое я знаю:

[HttpPut] 
[ActionName("Index")] 
public ActionResult IndexPut(Home home) 
{ 
    ... 
} 

В основном ActionNameAttribute был создан, чтобы иметь дело с этими сценариями.

+0

Джентльмен и ученый. Это выглядит так же изящно, как я могу сойти с рук :). – Dusda

0

HttpPut и HttpDeletes ограничены некоторыми брандмауэрами, поэтому порой используются только HttpPost и HttpGet. Если идентификатор записи передается (или некоторые другие критерии), вы знаете его обновление. Предоставленный - это для вас, чтобы определить, httpput может работать просто отлично для вас, это всего лишь предупреждение об этом, это обычно не очень важно.

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

 
ViewData["IdCheck"] = Encryption.ComputeHash(home.HomeId.ToString()); 

на ваш взгляд:

 
    <%: Html.Hidden("IdCheck", ViewData["IdCheck"]) %> 

в вашем HttpPost или HttpPut метод (в зависимости от того, что делает обновление)

 
if (Encryption.ComputeHash(home.HomeId.ToString()) != (string)Request.Form["IdCheck"]) 
{ 
     throw new Exception("Hashes do not match"); 
} 

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

+0

У нас есть ряд мер на месте, но я не рассматривал хэширование идентификаторов. Интересно. – Dusda

+1

проверьте http://www.nycdotnetdev.com/Download.aspx и выберите «1/20/2011 Hack-Proofing ваши веб-формы ASP.NET и веб-приложения MVC», загрузите один, если вы хотите получить более подробную информацию об этом –

Смежные вопросы