0
votes

I have a Web API in ASP.NET with OData and I can consume from the service, but the view doesn't print a table. I'm starting with .NET and with MVC.

ERROR: In View: @foreach (var item in Model)

System.NullReferenceException: Object reference not set to an instance of an object.

I have been seeing other similar doubts, which were solved by passing the model in the ActionResult, but I don't know how to do this with OData. Thanks!

MODEL

namespace exchange_rates
{
    using System;
    using System.Collections.Generic;

    public partial class CurrentValue
    {
        public int Id { get; set; }
        public System.DateTime Date { get; set; }
        public string Currency { get; set; }
        public double Rate { get; set; }
    }
}

CONTROLLER

namespace exchange_rates.Controllers
{
    public class CurrentValuesController : ODataController    
    {
        private db_test_bce_Entities db = new db_test_bce_Entities();

        // GET: odata/CurrentValues
        [EnableQuery]
        public IQueryable<CurrentValue> GetCurrentValues()
        {
            return db.CurrentValues;
        }

        // GET: odata/CurrentValues(5)
        [EnableQuery]
        public SingleResult<CurrentValue> GetCurrentValue([FromODataUri] int key)
        {
            return SingleResult.Create(db.CurrentValues.Where(currentValue => currentValue.Id == key));
        }
    }
}

WebApiConfig.cs

namespace exchange_rates
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<CurrentValue>("CurrentValues");
            config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
        }
    }
}

VIEW

@model IEnumerable<exchange_rates.CurrentValue>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>CurrenciesTable</title>
</head>
<body>
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Date)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Currency)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Rate)
            </th>
            <th></th>
        </tr>

        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Date)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Currency)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Rate)
                </td>
            </tr>
        }
    </table>
</body>
</html>

EDIT

I was trying return my list to the view from the OData Controller and this didn't work for me. Finally, I solved by returning the list from the MVC Controller:

HomeController

public class HomeController : Controller
{
    private db_test_bce_Entitiesdb = new db_test_bce_Entities();

    // GET: Home
    public ActionResult Index()
    {
        var currencies = db.CurrentValues.OrderBy(field => field.Acronym).ToList();

        return View(currencies);
    }
}
1
Your model doesn't look right. I would have though you would have needed an encapsulating ViewModel class that contains an IEnumerable of CurrentValue.. Then your view would say foreach var item in Model.CurrentValues which is your list of current values. - Wheels73
@Wheels73 sorry, but can you be more specific? I'm starting with C# and MVC. If I delete the foreach at least its prints the header of table. - yuya
hi... Your model is "CurrentValue". where is the collection of items you are iterating through... you've gone for each item in model... I'll post answer to show.... - Wheels73

1 Answers

0
votes
namespace exchange_rates
{
    using System;
    using System.Collections.Generic;

    public class MyViewModel   
    {
       public List<CurrentValue> MyListOfCurrentValues {get;set;} 
    }

    public class CurrentValue
    {
        public int Id { get; set; }
        public System.DateTime Date { get; set; }
        public string Currency { get; set; }
        public double Rate { get; set; }
    }
}

then in the view

 @foreach (var item in Model.MyListOfCurrentValues)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Date)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Currency)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Rate)
                </td>
            </tr>
        }

I'm not familiar with OData... but my controller would look like the below.

public ActionResult MyViewName()
{
            var model = new MyViewModel   
            {
                MyListOfCurrentValues = //Value from data source
            }


            return View("MyViewName", model);
}