简体   繁体   中英

Display data from single array JSON(azure Cosmos db) using C# ASP.NET MVC

I am trying to show data from Azure Cosmos DB (JSON data) using C# MVC web application. Json data is nested as below. I want to display information in Entries array as a table using c# MVC. I am not able to display data.

I am trying to show data from Azure Cosmos DB (JSON data). I checked few post on line which are doing it but they are using Json data strightway not Azure Jason. Json data is nested as below. I want to display information in Entries array ("dateTime": "2019-07-04T00:00:00", "precisCode": "showers-rain", "min": 10, "max": 19)as a table using c# MVC. I am new to both azure and c# mvcI am not able to display data. Please check code below and let me know whats wrong and what can be done.

Json data:

"id": "302620190704",
    "LocationId": "3026",
    "CreatedAt": "2019-07-04T21:42:53",
    "DateTime": "2019-07-04T00:00:00",
    "Entries": {
        "0": {
            "dateTime": "2019-07-04T00:00:00",
            "precisCode": "showers-rain",
            "min": 10,
            "max": 19
        }
    },
    "_rid": "sklTAKvKt1MBAAAAAAAAAA==",
    "_self": "dbs/sklTAA==/colls/sklTAKvKt1M=/docs/sklTAKvKt1MBAAAAAAAAAA==/",
    "_etag": "\"020002c6-0000-1a00-0000-5d1e906d0000\"",
    "_attachments": "attachments/",
    "_ts": 1562284141
}

Model:

namespace PelicanboatRamp.Models
{
    public class Weather
    {

        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }
        [JsonProperty(PropertyName = "DateTime")]
        public DateTime Datetime { get; set; }

        public static DateTime Today { get; }

        [JsonProperty(PropertyName = "LocationId")]
        public string LocationId { get; set; }

        [JsonProperty(PropertyName = "Entries")]
        public Entries entries { get; set; }
    }

    public class Entries
    {
        [JsonProperty(PropertyName = "precisCode")]
        public string Forecast { get; set; }

        [JsonProperty(PropertyName = "min")]
        public int MinTemp { get; set; }

        [JsonProperty(PropertyName = "max")]
        public int MaxTemp { get; set; }
    }
}

Controller:

 public class WeatherController : Controller
    {
        // GET: Weather
        [ActionName("Index")]
        public async Task<ActionResult> IndexAsync()

        {
            DateTime thisDay = DateTime.Today;
            var items = await DocumentDBRepository<Weather>.GetWeatherAsync(d => d.Id != null);
            items.Select(t => new Entries
            { Datetime = t.Datetime,
            Forecast = t.entries.Forecast,
            MinTemp = t.entries.MinTemp,
            MaxTemp = t.entries.MaxTemp
            }).ToList();
            return View(items);
        }
    }

DocumentDBRepository:

 public static async Task<IEnumerable<T>> GetWeatherAsync(Expression<Func<T, bool>> predicate)
        {
            IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
                UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId),
                new FeedOptions { MaxItemCount = 10, EnableCrossPartitionQuery = true })
                .Where(predicate)
                .AsDocumentQuery();

            List<T> results = new List<T>();
            while (query.HasMoreResults)
            {
                results.AddRange(await query.ExecuteNextAsync<T>());

            }

            return results;
        }
        public static async Task<T> GetWeatherAsync(string LocationId, string id)
        {
            try
            {
                //RequestOptions feedOptions = new RequestOptions { PartitionKey = new PartitionKey(Year) };
                Document document = await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id), new RequestOptions { PartitionKey = new PartitionKey(LocationId) });

                return (T)(dynamic)document;
            }
            catch (DocumentClientException e)
            {
                if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
                {
                    return null;
                }
                else
                {
                    throw;
                }
            }
        }


    }

Index:

@model IEnumerable<PelicanboatRamp.Models.Weather>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Todays Weather</h2>

 @foreach (var item in Model)
    {
        DateTime mydatetime = DateTime.Now;
       <h3>
            DateTime: @mydatetime
        </h3>
        <h3>
            Forecast:@Html.DisplayFor(modelItem => item.entries.Forecast)
        </h3>
        <h3>
            MinTemp:  @Html.DisplayFor(modelItem => item.entries.MinTemp)
        </h3>
        <h3>
            MaxTemp  @Html.DisplayFor(modelItem => item.entries.MaxTemp)
        </h3>

    }

I would like to display: (Current date and Time Forecaste: "showers-rain", minTemp: 10, maxTemp: 19

It's not displaying Forecast, Min Temp and Max Temp

First problem

Model classes incorrectly reflect the JSON structure. Here:

"Entries": {
    "0": {
        "dateTime": "2019-07-04T00:00:00",
        "precisCode": "showers-rain",
        "min": 10,
         "max": 19
    }
}

Entries is an object that contains numeric key 0 , and I guess might contain 1 , 2 , etc. Under every numeric key there is a single entry object.

To represent such a structure in C# we should use a dictionary, eg, Dictionary<string, Entry> (let's rename Entries to Entry , as it should represent a single entry object). Below is the correct model:

public class Weather
{
    // ... other properties

    // this property was declared incorrectly
    [JsonProperty(PropertyName = "Entries")]
    public Dictionary<string, Entry> Entries { get; set; }
}

// renamed from Entries
public class Entry 
{
    // ... properties
}        

Second problem

In the view, the model is declared as IEnumerable<...> while you seem to want to access a single instance of Weather . To list all entries from all Weather objects returned by the query, you should loop over the Model like this:

@{
    DateTime mydatetime = DateTime.Now;
    var allEntries = Model.SelectMany(m => m.Entries.Values);
}
@foreach (var entry in allEntries)
{
    <h3>
        DateTime: @mydatetime
    </h3>
    <h3>
        Forecast:@Html.DisplayFor(modelItem => entry.Forecast)
    </h3>
    <h3>
        MinTemp:  @Html.DisplayFor(modelItem => entry.MinTemp)
    </h3>
    <h3>
        MaxTemp  @Html.DisplayFor(modelItem => entry.MaxTemp)
    </h3>
}

BTW, this code in your controller:

items.Select(t => new Entries { 
    Datetime = t.Datetime,
    Forecast = t.entries.Forecast,
    MinTemp = t.entries.MinTemp,
    MaxTemp = t.entries.MaxTemp
}).ToList();

is completely redundant and has no effect.

If you want to display only a single Weather object

Then in the view, change the model to be of type Weather , and change the loop accordingly, as shown below:

@model PelicanboatRamp.Models.Weather
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@{
    DateTime mydatetime = DateTime.Now;
}
@foreach (var entry in Model.Entries.Values)
{
    <h3>
        DateTime: @mydatetime
    </h3>
    <h3>
        Forecast:@Html.DisplayFor(modelItem => entry.Forecast)
    </h3>
    <h3>
        MinTemp:  @Html.DisplayFor(modelItem => entry.MinTemp)
    </h3>
    <h3>
        MaxTemp  @Html.DisplayFor(modelItem => entry.MaxTemp)
    </h3>
}

In the controller, pick a single Weather object to pass to the view:

[ActionName("Index")]
public async Task<ActionResult> IndexAsync()
{
    DateTime thisDay = DateTime.Today;
    var items = await DocumentDBRepository<Weather>.GetWeatherAsync(d => d.Id != null);

    // select a single Weather object according to your business logic
    // for example like this:
    var todaysWeather = items.Single(weather => weather.DateTime.Date == thisDay);

    // pass the single Weather to the view
    return View(todaysWeather);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM