Маршрутизация службы ASP.NET REST - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь запустить службу REST ( Я следовал этому уроку ) и пытался расширить его простым способом, чтобы пометить один из ToDoItem как «Полный»;буквально для передачи идентификатора в метод, который должен пометить его как «Complete».

Однако я пытаюсь понять, как работает маршрутизация.

Этот метод предоставляется по умолчанию,который работает правильно через https://localhost:44388/api/values

Если я добавлю еще одну операцию GET, даже с другим атрибутом [Маршрут], то я получу «AmbiguousActionException: несколько действий совпадают»

[Route("api/values")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

Я попытался указать префикс маршрута, используя метод ниже, так что я мог добавить, не работает;Я получаю 404 на https://localhost:44388/api/values и https://localhost:44388/api/values/getbyname

[RoutePrefix("api/values")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [Route("getbyname")]
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

Возможно, я пытаюсь использовать неправильный метод, поэтому я рад принять любой совет.Я просто хочу иметь возможность создавать новые вызовы REST и выполнять их соответствующие действия.Нужно ли создавать другие контроллеры?Я ограничен одним GET / POST / PUT и т. Д. На контроллер?


Редактировать: недостаточно информации, вот еще код:

[Route("api/ToDo")]
[ApiController]
public class ToDoController : ControllerBase
{
    private readonly ToDoContext _context;

    public ToDoController(ToDoContext toDoContext)
    {
        _context = toDoContext;

        if (_context.ToDoItems.Count() == 0)
        {
            //collection is empty, so add a new item
            ToDoItem item1 = new ToDoItem(1, "example 1");
            ToDoItem item2 = new ToDoItem(2, "example 2");

            _context.ToDoItems.Add(item1);
            _context.ToDoItems.Add(item2);
            _context.SaveChanges();
        }
    }

    //GET: api/todo
    [HttpGet]
    public async Task<ActionResult<IEnumerable<ToDoItem>>> GetToDoItems()
    {
        return await _context.ToDoItems.ToListAsync();
    }

    //GET: api/todo/5
    //[HttpGet(Name = "Get a ToDoItem")]
    //[Route("get{id}")]
    [HttpGet("{id}")]
    public async Task<ActionResult<ToDoItem>> GetToDoItem(long id)
    {
        var todoitem = await _context.ToDoItems.FindAsync(id);

        if (todoitem == null)
        {
            return NotFound();
        }
        return todoitem;
    }

    //POST: api/Todo
    [HttpPost]
    public async Task<ActionResult<ToDoItem>> PostToDoItem(ToDoItem todoItem)
    {
        _context.ToDoItems.Add(todoItem);
        await _context.SaveChangesAsync();

        //calls the "GetToDoItem" method above!
        return CreatedAtAction("GetToDoItem", new { id = todoItem.ID }, todoItem);

    }

    //DELETE: api/todo/5
    [HttpDelete("{id}")]
    public async Task<ActionResult<ToDoItem>> DeleteToDoItem(long id)
    {
        var todoItem = await _context.ToDoItems.FindAsync(id);
        if(todoItem == null)
        {
            return NotFound();
        }

        _context.ToDoItems.Remove(todoItem);
        await _context.SaveChangesAsync();

        return todoItem;
    }



    //* -. space to create a "MarkAsComplete" method
    //GET: api/todo/5
    [HttpGet(Name = "{name}")]        
    public async Task<ActionResult<ToDoItem>> MarkAsComplete(long id)
    {
        var todoitem = await _context.ToDoItems.FindAsync(id);

        if (todoitem == null)
        {
            return NotFound();
        }
        else
        {
            todoitem.IsComplete = true;
        }
        return todoitem;
    }
    //*/
}

1 Ответ

0 голосов
/ 21 января 2019

Смешивание разных версий атрибутов. RoutePrefix из предыдущей версии.

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

Например.

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase {
    // GET api/values        
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get() {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/some_name 
    [HttpGet("{name}")]
    public IActionResult GetByName(string name) {
        return Ok();
    }
}

Ссылка Маршрутизация к действиям контроллера в ASP.NET Core

При создании REST API редко требуется использовать [Route(...)] для метода действия. Лучше использовать более конкретный Http*Verb*Attributes, чтобы быть точным в том, что поддерживает ваш API. Ожидается, что клиенты API REST будут знать, какие пути и HTTP-глаголы соответствуют определенным логическим операциям.

Исходя из предоставленной дополнительной информации, действие MarkAsComplete должно использовать HTTP PUT, что означает, что модель редактируется / обновляется.

Например

//* -. space to create a "MarkAsComplete" method
//PUT: api/todo/5
[HttpPut("{id:long}")]        
public async Task<ActionResult<ToDoItem>> MarkAsComplete(long id) {
    var todoitem = await _context.ToDoItems.FindAsync(id);
    if (todoitem == null) {
        return NotFound();
    } else {
        todoitem.IsComplete = true;
    }
    return todoitem;
}
//*/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...