7

I am new to asp.net core WebApi and I am trying to read data from a valid json file which is saved inside a folder called mydata inside my webapi

/mydata/userData.json

userData.json:

{
    "users": [
        {
            "id": 1,
            "firstName": "John",
            "lastName": "Doe"
        },
        {
            "id": 2,
            "firstName": "Jane",
            "lastName": "Doe"
        }
}

I wrote a web method that takes an input as first name, and returns single user object (first found record incase multiple results).

UserController.cs:

[Route("user/{firstName}")]  
public User GetUser(string firstName)  
{  
using (StreamReader r = new StreamReader("~/mydata/userData.json"))
    {
         string json = r.ReadToEnd();
         User item =JsonConvert.DeserializeObject<User>(json);
    }
    var user = User; 
    return user;  
} 

I am facing the following issues:

  1. I am not able to map the file userData.json, i tried Server.MapPath but it looks like its not available, httpcontext also did not work.
  2. I do not understand how to return a User Object from this api, which will be used in a react app.
user7050297
  • 117
  • 1
  • 1
  • 11

4 Answers4

5

You can achieve this by making use of IHostingEnvironment to get the root path and Path.Combine() method. So your controller should look like:

public class UserController : Controller
{
    private readonly IHostingEnvironment _hostingEnvironment;

    public UserController(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
    }

    [Route("user/{firstName}")]
    public User GetUser(string firstName)
    {
        var rootPath = _hostingEnvironment.ContentRootPath; //get the root path

        var fullPath = Path.Combine(rootPath, "mydata/user.json"); //combine the root path with that of our json file inside mydata directory

        var jsonData = System.IO.File.ReadAllText(fullPath); //read all the content inside the file

        if (string.IsNullOrWhiteSpace(jsonData)) return null; //if no data is present then return null or error if you wish

        var users = JsonConvert.DeserializeObject<List<User>>(jsonData); //deserialize object as a list of users in accordance with your json file

        if (users == null || users.Count == 0) return null; //if there's no data inside our list then return null or error if you wish

        var user = users.FirstOrDefault(x => x.FirstName == firstName); //filter the list to match with the first name that is being passed in

        return user;

    }
}

Please note: IHostingEnvironment will be removed in the future releases so if you can upgrade your framework then do so, so you can use the recommended IWebHostEnvironment type.

Izzy
  • 6,740
  • 7
  • 40
  • 84
  • Thanks, I am trying this approach. and getting this error: - $exception {"Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Collections.Generic.List`1[App.Models.User]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or ...... I will keep debugging. – user7050297 Aug 11 '21 at 21:40
  • Is this error in derealization happing because JSON file contains a "Users" object that contains a list of users (json file does not directly contains a list) ? – user7050297 Aug 11 '21 at 22:10
  • The `JSON` file content which you included in your question, the syntax was incorrect because you was missing the closing `]`. Before posting my answer yesterday, I added the closing `]` and manage to deserialize without any issues. If you're `JSON` file content has changed, please add it to your question and I will update my answer. – Izzy Aug 12 '21 at 08:01
5

Here is a working demo:

/mydata/userData.json:

{
  "users": [
    {
      "id": 1,
      "firstName": "John",
      "lastName": "Doe"
    },
    {
      "id": 2,
      "firstName": "Jane",
      "lastName": "Doe"
    }
  ]
}

project structure:

enter image description here

Model:

public class User
    {
        public List<UserModel> users { get; set; }
    }
    public class UserModel
    {
        public int id { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }


    }

action:

[Route("user/{firstName}")]
        public User GetUser(string firstName)
        {
            using (StreamReader r = new StreamReader("mydata/userData.json"))
            {
                string json = r.ReadToEnd();
                User item = JsonConvert.DeserializeObject<User>(json);
                return item;
            }
            return new User();
           
        }

result: enter image description here

Yiyi You
  • 16,875
  • 1
  • 10
  • 22
0

First of all, in asp.net core you are only able (by default) to read data from the wwwroot folder. If you want to change that, then refer here.

Second of all, you are trying to read only single object, but in you json file, there are multiple user objects. You can fix this by replacing your code User item =JsonConvert.DeserializeObject<User>(json); by this List<User> items = JsonConvert.DeserializeObject<List<User>>(json);

And finally, as mentioned in comments, when you StreamRead, you reference wrong file... Also it's better if you reference the file using enviromental variables

Hope I helped!

TDiblik
  • 522
  • 4
  • 18
0

1-) Sample path;

StreamReader r = new StreamReader(@"C:\Users\Suleyman\Desktop\users.json");

2-) sample;

  public List<User> GetUser(string firstName){}


List<User> item = JsonConvert.DeserializeObject<List<User>>(json);
Suleyman
  • 1
  • 3