我正在尝试从控制器添加Article
。但这是行不通的。当我使用邮递员时,出现错误500
ServiceFilter(typeof(LogUserActivity))]
[Route("api/users/{userId}/[controller]")]
[ApiController]
public class ArticleController : ControllerBase
{
private readonly IPrmRepository _repo;
private readonly IMapper _mapper;
public ArticleController(IPrmRepository repo, IMapper mapper)
{
_mapper = mapper;
_repo = repo;
}
public async Task<IActionResult> CretaArticle(int userId, ArticleForCreation articleForCreation)
{
var author = await _repo.GetUser(userId, false);
//check autorization
if (author.Id != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
return Unauthorized();
articleForCreation.AuthorId = userId;
var article = _mapper.Map<Article>(articleForCreation);
_repo.Add(article);
if (await _repo.SaveAll())
{
//Mapp Data to return db
var articleToReturn = _mapper.Map<ArticleToReturnDto>(article);
return CreatedAtRoute("GetArticle", new {id = article.ArticleId}, articleToReturn);
}
throw new Exception("Creating the article failed on save");
}
负责数据库中模型的模型:
public class Article
{
public int ArticleId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int AuthorId{get; set;}
public User Author { get; set; }
}
Dtos:
public class ArticleForCreation
{
public int AuthorId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
public class ArticleToReturnDto
{
public int Id { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
AutomapperProfile将数据映射到数据库:
CreateMap<ArticleForCreation, Article>().ReverseMap();
CreateMap<Article, ArticleToReturnDto>();
有人可以帮助您了解为什么它不起作用吗?
答案 0 :(得分:1)
没有实际的例外情况就不可能完全为您提供帮助。但是,以下行尖叫“错误”:
if (author.Id != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
在那一行中,您都有潜在的NullReferenceException
,FormatException
和ArgumentNullException
。
首先,您的控制器和操作均未使用Authorize
属性修饰,并且您未提供有关正在发出的请求以及是否包括{{ 1}}标头,也没有在Authorization
中正确配置身份验证以利用该标头。总而言之,很可能实际上没有用户本来就可以提出索赔。
每当您有可能为空的值(例如从Startup.cs
返回的值)时,都应进行空值检查。可以是实际的User.FindFirst
语句或三元语句,空偶数(if
)或较新的空条件(??
)。否则,如果尝试从碰巧为空的实例访问成员,则会抛出?.
。为此,实际上您可以做的最好的事情就是简单地使用NullReferenceException
,这样就不必再解除对User.FindFirstValue
成员的引用了。
接下来,如果返回的Value
最终为FindFirstValue
,则null
将抛出int.Parse
,因为您无法将ArgumentNullException
解析为{{1 }}。因此,在调用该值之前,您需要确保该值不为null。
然后,如果id实际上不是可以解析为null
的东西(例如GUID),则最终会抛出int
。您可能知道这是一个整数,但是您应该始终保护代码以防将来可能发生更改。当您需要将字符串解析为int(或与此相关的任何其他原始类型)时,应始终使用int
:
FormatException
总之,这是编写该行代码的一种更好的方法:
TryParse
从本质上说,如果索赔值为null /无法解析为int或不等于作者的id,则返回if (int.TryParse(myString, out int i)
{
// you can now use `i` as the parsed int for whatever you need
}
。