【问题标题】:ASP.NET Web API custom post action not workingASP.NET Web API 自定义发布操作不起作用
【发布时间】:2018-05-03 13:18:09
【问题描述】:

所以我的 API 中有一个 GebruikerController。 Gebruiker 是 User 的荷兰语,这个控制器的作用是登录用户,获取用户列表,添加用户并获取特定用户。但是我在为一个简单的登录功能引入自己的自定义post方法时遇到了一个问题。每当我从 PostMan 向函数发送一些数据时,我都会收到以下响应:

{"id":["值'login'无效。"]}

我用这个网址访问它:

http://localhost:52408/api/gebruikers/login

这是我的控制器:

[Produces("application/json")]
[Route("api/Gebruikers")]
public class GebruikersController : Controller
{
    private readonly flowerpowerContext _context;

    public GebruikersController(flowerpowerContext context)
    {
        _context = context;
    }

    // GET: api/Gebruikers
    [HttpGet]
    public IEnumerable<Gebruiker> GetGebruiker()
    {
        return _context.Gebruiker;
    }

    // GET: api/Gebruikers/5
    [HttpGet("{id}")]
    public async Task<IActionResult> GetGebruiker([FromRoute] int id)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var gebruiker = await _context.Gebruiker.SingleOrDefaultAsync(m => m.Id == id);

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

        return Ok(gebruiker);
    }

    [Route("api/gebruikers/login")]
    [HttpPost]
    public async Task<IActionResult> PostLogin([FromBody] string email, [FromBody] string password)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if(GebruikerVerify(email, password))
        {
            var gebruiker = await _context.Gebruiker.FirstOrDefaultAsync((g) => (g.GebruikerEmail == email && g.GebruikerWachtwoord == password));
            return Ok(gebruiker);
        }
        else
        {
            return BadRequest("invalid data");
        }
    }

    // PUT: api/Gebruikers/5
    [HttpPut("{id}")]
    public async Task<IActionResult> PutGebruiker([FromRoute] int id, [FromBody] Gebruiker gebruiker)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != gebruiker.Id)
        {
            return BadRequest();
        }

        _context.Entry(gebruiker).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!GebruikerExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return NoContent();
    }

    // POST: api/Gebruikers
    [HttpPost]
    public async Task<IActionResult> PostGebruiker([FromBody] Gebruiker gebruiker)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        _context.Gebruiker.Add(gebruiker);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetGebruiker", new { id = gebruiker.Id }, gebruiker);
    }

    // DELETE: api/Gebruikers/5
    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteGebruiker([FromRoute] int id)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var gebruiker = await _context.Gebruiker.SingleOrDefaultAsync(m => m.Id == id);
        if (gebruiker == null)
        {
            return NotFound();
        }

        _context.Gebruiker.Remove(gebruiker);
        await _context.SaveChangesAsync();

        return Ok(gebruiker);
    }

    private bool GebruikerExists(int id)
    {
        return _context.Gebruiker.Any(e => e.Id == id);
    }

    private bool GebruikerVerify(string email, string wacthwoord)
    {
        if(_context.Gebruiker.Any(e => e.GebruikerEmail == email))
        {
            Gebruiker gebruiker = _context.Gebruiker.FirstOrDefault(e => e.GebruikerEmail == email);
            if(wacthwoord == gebruiker.GebruikerWachtwoord)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
}

以下代码是我的登录代码,在上面的代码中也可以看到。

        [Route("api/gebruikers/login")]
    [HttpPost]
    public async Task<IActionResult> PostLogin([FromBody] string email, [FromBody] string password)
    {
        if(!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if(GebruikerVerify(email, password))
        {
            var gebruiker = await _context.Gebruiker.FirstOrDefaultAsync((g) => (g.GebruikerEmail == email && g.GebruikerWachtwoord == password));
            return Ok(gebruiker);
        }
        else
        {
            return BadRequest("invalid data");
        }
    }

    private bool GebruikerVerify(string email, string wacthwoord)
    {
        if(_context.Gebruiker.Any(e => e.GebruikerEmail == email))
        {
            Gebruiker gebruiker = _context.Gebruiker.FirstOrDefault(e => e.GebruikerEmail == email);
            if(wacthwoord == gebruiker.GebruikerWachtwoord)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

我对此很陌生,我对我在这里做错了什么一无所知。有人可以帮我解决这个问题吗?

【问题讨论】:

  • 路由问题。由于控制器上的路由前缀,您正在点击 GetGebruiker,它期望 id 是 int,但它看到 login
  • next FromBody 只能在操作参数中使用一次。将这些参数合并到一个模型中,然后使用FromBody 属性
  • login被认为是一个POST请求时,您还需要指定使用了哪个HTTP动词。
  • 如果使用路由前缀,则不需要在操作路由中包含前缀。
  • 所以我需要移除 rout 并更改 FromBody 参数?

标签: c# asp.net-core asp.net-core-webapi asp.net-core-routing


【解决方案1】:

这是一个路由问题。由于控制器上的路由前缀,您正在点击GetGebruiker,它期望idint,但它看到"login" 字符串。

下一个FromBody 只能在操作参数中使用一次。将这些参数合并到一个模型中,然后使用FromBody 属性。

public class LoginModel {
    [Required]
    public string email { get; set; }
    [Required]
    public string password { get; set; }
}

注意用于演示映射路线的 cmets。

[Produces("application/json")]
[Route("api/Gebruikers")]//route prefix for this controller
public class GebruikersController : Controller {
    //...code removed for brevity

    // GET: api/Gebruikers
    [HttpGet]
    public IEnumerable<Gebruiker> GetGebruiker() {
        //...code removed for brevity
    }

    // GET: api/Gebruikers/5
    [HttpGet("{id:int}")] // Note the route constraint
    public async Task<IActionResult> GetGebruiker([FromRoute] int id) {
        //...code removed for brevity
    }

    // POST: api/Gebruikers/login
    [HttpPost("login")]
    public async Task<IActionResult> PostLogin([FromBody] LoginModel login) {
        if(!ModelState.IsValid) {
            return BadRequest(ModelState);
        }

        if(GebruikerVerify(login.email, login.password)) {
            //...code removed for brevity
        } else {
            return BadRequest("invalid data");
        }
    }

    // PUT: api/Gebruikers/5
    [HttpPut("{id:int}")]
    public async Task<IActionResult> PutGebruiker([FromRoute] int id, [FromBody] Gebruiker gebruiker) {
        //...code removed for brevity
    }

    // POST: api/Gebruikers
    [HttpPost]
    public async Task<IActionResult> PostGebruiker([FromBody] Gebruiker gebruiker) {
        //...code removed for brevity
    }

    // DELETE: api/Gebruikers/5
    [HttpDelete("{id:int}")]
    public async Task<IActionResult> DeleteGebruiker([FromRoute] int id) {
        //...code removed for brevity
    }

    //..code removed for brevity
}

参考文献

Routing in ASP.NET Core # Route Constraint Reference

Routing to Controller Actions

Model Binding

【讨论】:

  • 啊好的,我必须发送这个对象:“login”:[{“email”:“email@mail.com”,“password”:“test”}]如果我是对吗?
  • @B.Hulshof 对象就是{ "email" : "email@mail.com", "password" : "test" }。模型绑定器会将其映射到 action 参数。您在上一条评论中的内容是一个数组而不是单个对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 2012-08-20
  • 2011-10-01
相关资源
最近更新 更多