【问题标题】:Web Api 2 with two method with the same HTTP verb an angularjs resourcesWeb Api 2 具有两种方法,具有相同的 HTTP 动词和 angularjs 资源
【发布时间】:2015-05-13 13:47:51
【问题描述】:

我有这个控制器:

public class SeguiAttivazioneController : ApiController
{
    [HttpGet]
    public IHttpActionResult DoWork1()
    {
        ...            
        return Ok();
    }

    [HttpGet]
    public IHttpActionResult DoWork2()
    {
        ...            
        return Ok();
    }

    [HttpGet] //I would like to have a search with GET verb, but I cannot validate my ModelState with dataAnnotation
    public IHttpActionResult AnotherSearch(string filter1, string filter2, ...)
    {
        if (ModelState.IsValid)
        {
            ...
            return Ok();
        }
        return BadRequest(ModelState);
    }

    [HttpPost]
    public IHttpActionResult DoSearch(SearchFilter filters)
    {
        if (ModelState.IsValid)
        {
            ...
            return Ok();
        }
        return BadRequest(ModelState);
    }

    [HttpPost]
    public IHttpActionResult SubmitForm(FormData data)
    {
        ...
        return Ok();
    }
}

如您所见,我有两种具有相同 HttpVerbs 的方法(2 个用于 GET,2 个用于 POST)...我不知道我是否违反了 REST 原则...如果是这样,我想避免... . 在这一刻,我正在使用 AngularJs + NgResources 来调用我的 Controller..

public_area
    .factory("SeguiAttivazioneService", function ($resource) {
        //return {
        //    seguiAttivazione: $resource("/api/SeguiAttivazione/", null,
        //                        {
        //                            'get2': { method: 'GET', url: '/api/SeguiAttivazione/GetActivationStatus2' }
        //                        })
        //};
        return {
            seguiAttivazione: $resource("/api/SeguiAttivazione/")
        };
    });

我正在尝试做一个 GET:

$scope.getActivationStatus = function (event) {
    event.preventDefault();

    if ($scope.segui_attivazione_form.$valid) {
        var request =
            new SeguiAttivazioneService
                .seguiAttivazione()
                .$get({ }, getActivationStatusSuccess, getActivationStatusError);
    }
};

但是(正确地)我得到一个“内部服务器错误 500”,因为我必须使用 GET 方法。我怎么解决这个问题? (我想我也会遇到同样的问题)

谢谢

更新 这里是过滤器的类

public class SearchFilter 
{
    [Required(ErrorMessage="")]
    public string CodiceFiscale { get; set; }
    [Required(ErrorMessage = "")]
    [RegularExpression(@"^(?:\d{11,16})|(?:[a-zA-Z]{6}[a-zA-Z0-9]{2}[a-zA-Z][a-zA-Z0-9]{2}[a-zA-Z][a-zA-Z0-9]{3}[a-zA-Z])$", ErrorMessage = "Codice Fiscale o Partita IVA non validi")]
    public string CodiceRichiesta { get; set; }
}

有了这个类,我可以使用数据注释来验证我的模型......如果我使用 GET 方法,我将无法再使用数据注释验证......

【问题讨论】:

  • REST 端点应该具有歧视性。看看这篇维基百科文章的例子(可能不是最好的来源,但例子很好)en.wikipedia.org/wiki/Representational_state_transfer。 URI 上的方法在您的后端应该只有一个入口点
  • 所以你的意思是我应该只有一个 GET 和一个 POST?
  • 对于 URI 端点是的。我将尝试对 REST Uri 做一个简短的回答
  • Simone,我想我回答了你原来的问题。如果现在您对使用数据注释进行验证有不同的问题,请不要在您当前的问题中混淆。创建一个新问题,您现在可以在其中解释您想要做什么。这将使某人更有可能回答它。我脑子里有一些想法,但你的问题并不清楚。请清楚地解释新的风景,并明确这篇文章的任何答案是否回答了您的原始问题。谢谢。

标签: angularjs rest asp.net-web-api2 ngresource


【解决方案1】:

这里是关于 REST Endpoints 的一些解释。

在 REST 中,我们正在操纵资源。作为收藏或个人。

Classics 端点是:

GET /rest/houses DATA : none -> will return a collection of houses

GET /rest/houses/{id} DATA : none -> will return the house find by its {id}

POST /rest/houses DATA : {"street":"3 bdv NY-city"} -> will create a new house object with the given data

PUT /rest/houses/{id} DATA : { "id":"{id}", "street":"4 bvd NY-city"} -> will update the whole house ressource find by its {id}

PATCH /rest/houses/{id} DATA : { "street":"4bvd NY-city" } -> will update the given fields of the house ressource find by its {id}

DELETE /rest/houses/{id} DATA : none -> will delete the house ressource find by its id.

关于restfull API 的事情太多了,我不能给你所有的密钥。但是尝试找到一些关于这些主题的好文章,例如:

http://www.restapitutorial.com/index.html

不确定这是否能回答您的问题,但希望对您有所帮助。

编辑 1:

由于我必须添加一些关于restfull 方式的要点来执行一些复杂的操作,所以我会给你restfull url 的方式。

在一个宁静的世界(非常罕见)你只知道你的 rest API 的一个入口点让我们这样说:

GET /rest/

此 uri 将响应您将 api 可以提供的所有服务 例子:

{
 "resources":"/rest/ressources",
 "apiInfo" : "/rest/api/info"
}

要获取资源信息,请点击链接

 GET response.resources

我可能会这样回答:

{
 "houses":"/rest/ressources/houses/",
 "cars"  :"/rest/ressources/cars"
}

现在我们想要房子

GET response.houses

回应:

 {
  "fields":[{
    "constructionYear","street"
   }],
  "search":"/rest/houses"
  "create":"/rest/houses"
 }

等等...在这个地方你可以添加一些非宁静的端点。以一种安宁的方式。这个动作将由一个安静的资源持有。 Somes API 正在使用这种很棒的 Restful。

标准休息 API: https://developers.soundcloud.com/docs/api/reference#users

宁静的 API: https://www.salesforce.com/us/developer/docs/api_rest/

【讨论】:

  • 清除.. 谢谢... 在这一点上,这正是我的问题.. 我有一个搜索 (POST).. 但如果我的搜索没有找到任何东西,我必须创建对象..所以我做了一个创建(POST)......我有两个相同的REST服务的POST......老实说,我认为搜索应该是GET,但如果我在GET中转换我的搜索,我无法使用数据注释验证我的ModelState.. . 我更新了我的问题
  • 为什么不分两步做呢?首先,您使用 GET 进行搜索,当 GET 响应返回但没有结果时,您会触发 POST 请求来创建资源。我不确定我是否对使用数据注释进行验证有问题。你想验证你的 GET 参数吗?
  • 是的,我需要验证它们,因为它们必须尊重一些“模式”:例如意大利财政代码(XXXXXX00X00X000X)......我已经在客户端进行了检查,但我认为它是如果我在服务器端也这样做会更好..
  • 不幸的是我对asp.net一无所知,也许如果你想遵循其他原则,你应该问另一个问题,重点是“如何通过带有数据注释的ModelState验证GET url参数”如果你不'不介意休息一下,您可以创建一条其他路线,例如 POST /myressource/search,其余路线仍然相同:POST /myressource/ -> 创建资源。
【解决方案2】:

问题是 Web API 基础架构必须有一种方法来选择其中一种可能的方法。

一种方法是更改​​ Web API 路由配置,包括 /{action}/ 段。如果您这样做,它将完全像 MVC 一样工作,并且您必须始终包含操作名称。

另一种方法是在每个方法中设置不同的接收参数,以便 Web API 基础架构可以发现您尝试调用的方法。您可以阅读我今天为类似问题写的这个答案:How can I add multiple Get actions with different input params when working RESTFUL?

作为该答案的最后评论,我说参数也可以通过使用路由约束来识别。

必须在所有调用中包含操作名称的第一个解决方案不是 RESTful,但您是否出于任何特定原因需要或更喜欢它是 RESTful?

【讨论】:

  • 不,我不需要,我更喜欢......我认为如果我尊重 RESP 原则会更好......还是不?
  • REST 原则只是统一 API 定义的一种方式。如果您遵循这一点,您将对如何以及可以在 API 中执行的操作有一个清晰而简单的区分。
  • 这不是最好的或最差的... id 取决于您想要达到的目标。不管怎样,你知道有没有保持它 RESTful 的工具。在我看来,URL 方面并不是 RESTful API 中最重要的部分,而且,如果您的 API 中有很多业务逻辑,则很难进行 RESTful 实现。如果您做了类似数据服务的事情,其中​​没有任何或很少的业务对象,那么您可以轻松地将其设为 RESTful(这就是 ODATA!)。所以,我不会太担心。
  • @Okazari 如果您阅读了我的评论,也许您会同意,如果您在 API 中有很多业务逻辑而不是使其更清晰,那么您可能会使其更加混乱。如果您只是简单地读取、删除和修改数据等等,那将非常清楚。这是我的个人意见,但我想知道你的意见。
  • @Okazari。那么我们同意,如果您需要的不仅仅是编辑数据,那么制作 RESTful API 会毫无理由地复杂化。将这些链接公开到与公开集合相关的操作很难做到,而且我真的怀疑它是否会给服务用户带来好处。如果您想公开数据,可以使用开箱即用的 RESTful 解决方案,例如 ODATA,几乎可以零努力地实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2016-05-02
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 2017-02-22
  • 2017-06-19
相关资源
最近更新 更多