【问题标题】:C# Controller behavior changes based on variable nameC# 控制器行为根据变量名改变
【发布时间】:2023-01-15 00:23:31
【问题描述】:

我对 C#、.NET 或 MVC 模式的了解还不够,无法确切地知道要在此处包含哪些相关内容,但我正在通过一个非常简单的更改来解决问题。

我有一个带有搜索操作(方法?)的控制器,如下所示:

public string Search(int id)
{
    return $"The id was {id}";
}

当我到达路线时,我得到了预期的回应,例如

$ curl https://localhost:7180/Players/Search/1
The id was 1

但是当我将变量名从 id 更改为其他任何名称时,行为会发生变化并且由于某种原因该值变为 0。

public string Search(int thing)
{
    return $"The thing was {thing}";
}
$ curl https://localhost:7180/Players/Search/1
The thing was 0

我认为这可能与模型本身有关,因为模型代码至少具有 Id 属性

    public class Player
    {
        public int Id { get; set; }
        public string? Name { get; set; }
    }

但将该变量重命名为 name(这看起来很相似)也无济于事。

那么我在这里缺少什么概念?为什么我不能将该变量重命名为我想要的任何名称?提前致谢!

(我不知道如何更好地传达代码的所有不同方面,所以这里是link to the line in question, inside the project

【问题讨论】:

  • 在你的控制器中,尝试:[HttpGet("{thing}")] public string Search(int thing) { return $"The thing was {thing}"; }
  • 啊,是的,在Program.cs我有声明app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");

标签: c# asp.net-mvc


【解决方案1】:

默认情况下,MVC 注册(请参阅 ProgramStartup)下一个默认路由,因此它可以将方法的 id 参数绑定为路径的位置部分:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

您可以更改参数名称,例如使用attribute routing

[Route("[controller]/search/{thing}")] 
public string Search(int thing)
{
    return $"The thing was {thing}";
}

或者使用HTTP verb templates

[HttpGet("[controller]/search/{thing}")] 
public string Search(int thing)
{
    return $"The thing was {thing}";
}

检查链接文档以获取其他选项/详细信息。

【讨论】:

    【解决方案2】:

    我相信这与您在 Program.cs 中使用 defined your route 的方式有关:

    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    

    您需要像这样添加一个新定义:

    app.MapControllerRoute(
        name: "default",
        pattern: "Players/Search/{thing?}");
    

    或者,您可以使用基于属性的路由定义来使路由模式定义更接近实际代码。有关详细信息,请参阅MSFT docs。基本上,将 app.MapControllers(); 添加到 Program.cs,然后对于您的个人路线,执行如下操作:

    [Route("Players/Search/{thing}")]
    public string Search(int thing)
    {
        return $"The thing was {thing}";
    }
    

    【讨论】:

      【解决方案3】:

      您可以装饰方法并定义参数。

          // GET api/values/5
          [HttpGet("{id}")]
          public virtual async Task<ActionResult<IEntity>> Get(string id)
          {
              var entity = await Repository.GetEntity(x => x.Id == id);
              if (entity == null) return NotFound();
      
              return Ok(entity);
          }
      

      这是 API 控制器的另一个示例

      [Route("api/[controller]")]
      [ApiController]
      public class UserController : ControllerBase
      {
          private readonly GameDataContext context;
      
          public UserController(GameDataContext context)
          {
              this.context = context;
          }
      
          // GET: /<controller>/
          // GET api/user
          [HttpGet]
          public ActionResult<IEnumerable<User>> Get()
          {
              
      
              return context.Users.Where(x => x.IsDeleted == false).ToArray();
          }
      
          // GET api/user/5
          [HttpGet("{id}", Name = "GetUser")]
          public ActionResult<User> Get(int id)
          {
              var user = context.Users.FirstOrDefault(x => x.Id == id && x.IsDeleted == false);
              if (user != null)
              {
                  return user;
              }
      
              return NotFound();
          }
      
          // GET api/user/username/5
          [HttpGet("username/{id}", Name = "GetUserByGameId")]
          public ActionResult<User> GetByUser(string gameId)
          {
              var user = context.Users.FirstOrDefault(x => x.UserGameId.Equals(gameId) && x.IsDeleted == false); 
              if (user != null)
              {
                  return user;
              }
      
              return NotFound();
          }
      
          // POST api/user
          [HttpPost]
          public async Task<ActionResult> Post([FromBody] User value)
          {
              if (value == null)
              {
                  return BadRequest();
              }
      
              var user = context.Users.FirstOrDefault(x => x.UserGameId.Equals(value.UserGameId) && x.IsDeleted == false);
              if (user != null)
              {
                  return BadRequest("User already exists!");
              }
      
              context.Users.Add(value);
              await context.SaveChangesAsync();
      
              return CreatedAtRoute("GetUser", new { id = value.Id }, value);
          }
      
          // PUT api/user/steamId
          [HttpPut("{gameId}")]
          public async Task<ActionResult> Put(string gameId, [FromBody] User value)
          {
              if (value == null || !value.UserGameId.Equals(gameId))
              {
                  return BadRequest();
              }
              var user = context.Users.FirstOrDefault(x => x.UserGameId.Equals(gameId) && x.IsDeleted == false); 
              if (user == null)
              {
                  return NotFound();
              }
      
              user.UserGameId = value.UserGameId;
              user.FirstName = value.FirstName;
              user.MiddleName = value.MiddleName;
              user.LastName = value.LastName;
              user.Email = value.Email;
      
              context.Users.Update(user);
              await context.SaveChangesAsync();
      
      
              return new NoContentResult();
          }
      
          // DELETE api/user/steamId
          [HttpDelete("{gameId}")]
          public async Task<ActionResult> Delete(string gameId)
          {
              if (string.IsNullOrEmpty(gameId))
              {
                  return BadRequest();
              }
      
              var user = context.Users.FirstOrDefault(x => x.UserGameId.Equals(gameId) && x.IsDeleted == false);
              if (user == null)
              {
                  return NotFound();
              }
      
              user.IsDeleted = true;
              context.Users.Update(user);
      
              var scores = context.Scores.Where(x => x.UserId == user.Id);
              foreach (var score in scores)
              {
                  score.IsDeleted = true;
                  context.Scores.Update(score);
              }
      
              await context.SaveChangesAsync();
      
              return new NoContentResult();
          }
      }
      

      【讨论】:

      • 谢谢回复!据我所知,在您的文档字符串中的 GET api/values/5 示例中,像那样使用此装饰器会将 api 分配给 id。根据你的建议,我在我的路线 (/Players/Search/1) 上收到了 404,但当我访问 /Players 时,我看到了 "the thing was Players"
      • 不客气!不,它会将“5”分配给“id”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多