在Controler Asp net .core中添加文章

时间:2018-08-31 09:51:37

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

我正在尝试从控制器添加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>();

有人可以帮助您了解为什么它不起作用吗?

1 个答案:

答案 0 :(得分:1)

没有实际的例外情况就不可能完全为您提供帮助。但是,以下行尖叫“错误”:

if (author.Id != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))

在那一行中,您都有潜在的NullReferenceExceptionFormatExceptionArgumentNullException

首先,您的控制器和操作均未使用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 }