【问题标题】:How do I display my Json Objects on a web api?如何在 Web api 上显示我的 Json 对象?
【发布时间】:2021-07-16 18:07:53
【问题描述】:

我正在开发 ASP.NET Web Api,但在弄清楚如何将数据显示到 api 时遇到问题。

所以解释一下我需要弄清楚的。从 Json 文件和converting JSON to a .NET type. 访问对象后,我相信我应该能够在 api 上显示这些?

例如,无论我要求什么字段,它都应该返回按该字段排序的结果。 现在我需要在不同的端口显示这些数据。例如。

  • https://host:port/api/books 返回所有未排序的 (Book1-Book13)
  • https://host:port/api/books/id 返回所有按 id 排序的 (Book1-Book13)
  • https://host:port/api/books/id/1 返回所有 id 包含 '1' 按 id 排序的内容(Book1、Book10-13)

我已经关注了这个tutorial by microsoft,并且该应用程序似乎在启动和使用不同的端口方面正在工作。

这是我在控制器类BooksController.cs中设置的代码

 [Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
    [HttpGet]
    public ActionResult GetAllBooks()
    {
        string[] books = { "book1", "book2", "book3" };

        if (!books.Any())
            return NotFound();
        return Ok(books);
    }

    [HttpGet("id/{id}")]
    public string GetBookById(int id)
    {

        return $"book: {id}";
    }

    [HttpGet("author/{author}")]
    public string GetBookByAuthor(string author)
    {
        return $"author: {author}";
    }

这是我的startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
        GetAllBooks();
    }
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<TodoContext>(opt =>
                                           opt.UseInMemoryDatabase("TodoList"));
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();
        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

    
    public void GetAllBooks()
    {
        string _path = $"C:\\Users\\filip\\source\\repos\\NexerGroupApi\\NexerGroupApi\\books.json";

        string jsonFromFile;
        using (var reader = new StreamReader(_path))
        {
            jsonFromFile = reader.ReadToEnd();
        }

        var booksFromJsonFile = JsonConvert.DeserializeObject<List<NexerGroupApi.Book>>(jsonFromFile);

        JArray bookArray = JArray.FromObject(booksFromJsonFile);

        IList<Book> bookList= bookArray.Select(p => new Book
        {
            Id = (string)p["Id"],
            Author = (string)p["Author"],
            Title = (string)p["Title"],
            Genre = (string)p["Genre"],
            Price = (string)p["Price"],
            Publish_date = (string)p["Publish_date"],
            Description = (string)p["Description"]
        }).ToList();
    }

    public class Book
    {
        public string Id { get; set; }
        public string Author { get; set; }
        public string Title { get; set; }
        public string Genre { get; set; }
        public string Price { get; set; }
        public string Publish_date { get; set; }
        public string Description { get; set; }
    }

我想知道我在哪里实际设置了我的 GetAllBooks() 方法,以便我可以在 BooksController.cs 中访问它们并能够执行 api/books/bookNameFromJsonFile 并显示该特定对象及其所有内容,例如 id 、作者、标题、流派等。

我知道startup.cs 类中的IList&lt;Book&gt; bookList 不起作用,由于某种原因,每个变量都获得了空值。虽然不知道为什么。

【问题讨论】:

  • @mason 好的,所以我现在一直在看几个教程 - youtube.com/… - 我会更新我的问题,也许你可以回答这个问题?
  • 您不需要为您拥有的每一本书设置单独的路线。您需要构造您的路线以具有参数。检查the documentation
  • @mason 好的,我已经查看了那个链接和一个 youtube 视频。据我了解,我然后做例如 [HttpGet("{id}")] 然后我以该方法遍历我的书,然后如果我输入“api/book/2”,它将检索 id=2 的书。它是否有效,以便我可以在我有一个字符串作者的地方执行 [HttpGet("{author}")],所以如果我执行 api/books/authorname,我实际上会收到该作者的书吗?
  • 我编辑了这个问题,向您展示我认为可行的方法。我的 startup.cs 中是否存在导致此错误代码的问题?
  • 这是你的路线定义。就像错误所说的那样,您的路由匹配多个端点。很可能它很生气,因为它不知道要针对/api/books/1 之类的URL 使用哪个操作方法,它不知道1 是ID 还是作者。对于 GetBookByAuthor,您可以将其更改为 [HttpGet("author/{author}")],然后希望按作者查找书籍的人将点击 URL /api/books/author/Tom%20Clancy,并将 GetBookById 更改为 [HttpGet("id/{id}")],以便他们可以点击 URL /api/books/id/1。这使它毫不含糊。只需考虑一下您的路线结构。

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


【解决方案1】:

正如错误提示的那样,您有两条不明确的路线 [HttpGet("{id}")][HttpGet("{author}")]

给定

当您点击 api/books/1 时,1 可能是作者或 bookid。

考虑将 author 方法的路由改为: [HttpGet("author/{author}")]

[HttpGet("{id}")]
public string GetBookById(int id)
{
    
    return $"book: {id}";
}

[HttpGet("author/{author}")] 
public string GetBookByAuthor(string author)
{
    return $"author: {author}";
}

因此请求将按如下方式路由:

api/books/1 会调用 GetBookById

api/books/author/jsmith 将调用 GetBookByAuthor

编辑:添加列表过滤:

要从List&lt;Book&gt; 中找到Book,可以这样做:

private readonly List<Book> _bookList; //populate this with books from json file

[HttpGet("{id}")]
public IActionResult GetBookById(int id)
{
    var book = GetBookObjectById(id);
    if(book is null) return NotFound();
    return Ok(book);
}

private Book GetBookObjectById(int id)
{
    return _bookList.FirstOrDefault(book => book.Id == id);
}

private Book GetBookObjectByAuthor(string author)
{
    return _bookList.FirstOrDefault(book => book.Author == author);
}

【讨论】:

  • 感谢您的提示!我解决了这个问题并进行了设置,以便我可以输入例如 api/books/id/1api/books/title/bookTitle 。我现在想知道的一件事是以下.. 我从file.json 获取我的 Json 数据我在哪里设置它来加载所有数据?最后,我希望能够做到api/books/bookNameFromJsonFile 并显示该特定对象及其所有内容,例如 id、作者、标题、流派等。如果您查看我的startup.cs,我已经在那里设置了它并且那你看看我的booksController.cs长什么样子,是不是走错路了?
  • 我更新了我的问题,所以如果您现在查看它,您可以看到我在哪里以及困扰我的问题。我还没有找到任何我能真正理解的东西。
  • 如果这只是一个学习练习,那么我个人会将您在Startup.cs 中的loadbook 代码放入控制器中,以便在构造函数中创建它。在现实世界中,您会创建一个 BookService 并使用依赖注入将其注入控制器。
  • 您的 json 反序列化代码也可以得到很大的改进 - 看看这里的微软文档:docs.microsoft.com/en-us/dotnet/standard/serialization/…
  • 这更像是一种学习练习,而不是真实世界的场景。我知道我应该开始学习正确的方法,但是在我了解我正在做的事情之后,我更容易通过这种方式学习然后改进代码。而不仅仅是 Ctrl+V 一切。我现在已经成功地打印了所有的书。但是有没有办法将这些打印为 json 对象? id1 在哪里 1 {} 等等?这就是我显示它们的方式public ActionResult GetAllBooks(){if (!bookList.Any())return NotFound(); return Ok(bookList);},但这很麻烦而且无法阅读。
猜你喜欢
  • 2019-07-12
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多