`Model.plans.Count` 抛出类型为'System.NullReferenceException` 的异常

`Model.plans.Count` threw an exception of type 'System.NullReferenceException`

我正在尝试将字符串对象列表显示为复选框。我有两个项目,ASP.NET Core MVC 应用程序项目和 ASP.NET Core Web API 都 运行 在 5.0 NET Core 上运行。在 MVC 项目中,我正在调用 Web API 项目,它将在其中创建一个新的对象列表。然后在我的 MVC 项目中我做了一个项目引用来调用视图中的控制器。当我 运行 应用程序时,MVC 将命中它调用 API 项目的行。在我的 API 控制器的 GetPlan() 方法中存储新创建的对象后,我尝试在我的 MVC 视图中将这些创建的对象显示为复选框。但是,当我这样做时,它说 Model.plans.Count 抛出了 System.NullReferenceException 类型的异常。然后进一步查看它,它只会告诉我:

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

Microsoft.AspNetCore.Mvc.Razor.RazorPage.Model.get returned null.

我不明白为什么我在已经创建了新对象的情况下返回 null。

MVC 项目:

Controller 我打电话给 API:

 public IActionResult SecIndex()
    {
        // call planapi
        var result = _planServiceClient.RetrievePlans().Result;
        _logger.Log(LogLevel.Information, "Reached the Second Page View....");
        return View();
    }

然后是我的 API 项目:

Model class for ViewPhoneNumberInput:

  public class ViewPhoneNumberInput
    {
        [Required(ErrorMessage = "You did not enter your phone number! Please enter your phone number!")]
        public String PhoneNumber { get; set; }
        public List<Plans> plans { get; set; }
    }

我的计划模型class:

    public class Plans
    {
        public int PlanId { get; set; }
        public string PlanName { get; set; }
    }

Controller 对于 api:

        [HttpGet]
        [Route("AvailablePlans")]
        public ActionResult GetPlan()
        {

            var _model = new ViewPhoneNumberInput();
            _model.plans = new List<Plans>();

            _model.plans.Add(new Plans { PlanId = 1, PlanName = "Internet" });
            _model.plans.Add(new Plans { PlanId = 2, PlanName = "TV & Streaming" });
            _model.plans.Add(new Plans { PlanId = 3, PlanName = "Mobile" });
            _model.plans.Add(new Plans { PlanId = 4, PlanName = "Home Security" });
            _model.plans.Add(new Plans { PlanId = 5, PlanName = "Home Phone" });


            var plansAvailable = JsonSerializer.Serialize(_model.plans);
            _logger.Log(LogLevel.Information, "Response-Body: {@Response-Body}", plansAvailable);


            return Ok(_model.plans);
        }

上面 _model.plans 将保存创建的新对象的值,所以我去我的 MVC 视图项目调用它,这样我就可以显示它,但这就是它说 Model.plans.Count 引发了类型为“System.NullReferenceException”的异常。

View 对于 MVC 项目:

@model Plan.API.Models.ViewPhoneNumberInput


<h2>Second page</h2>




@using (Html.BeginForm())
{

    for (int i = 0; i < Model.plans.Count; i++)
    {
        <input type="checkbox" id="@Model.plans[i].PlanId" name="Model.plans[i].PlanId" />
        <label for="Model.plans[i].PlanId"> @Model.plans[i].PlanName </label> <br />
    }


    @Html.TextBoxFor(r => r.PhoneNumber)
    <input id="Button" type="submit" value="Next" />

    <p>  @Html.ValidationMessageFor(r => r.PhoneNumber) </p>

}

为什么它告诉我这个而不是实际保存来自 API 控制器的新创建的值?


在实施下面的建议时,我能够看到 PhoneNumber 的值,但对于 Plans,它显示为空(当鼠标悬停在 post SecIndex 中的 phoneNumberInput 上时)。

我的检索计划():

        public async Task<List<Plan.API.Models.Plans>> RetrievePlans()
        {
            var response = await _httpClient.GetAsync("api/plans/AvailablePlans");
            response.EnsureSuccessStatusCode();

            var result = await response.Content.ReadAsStringAsync();

           var json = JsonConvert.DeserializeObject<List<Plan.API.Models.Plans>>(result);

            return json;
        }

我的更新 SecIndex() with Post SecIndex():

        public IActionResult SecIndex()
        {
            // call planapi
            var result = _planServiceClient.RetrievePlans().Result;
            _logger.Log(LogLevel.Information, "Reached the Second Page View....");
            return View(new Plan.API.Models.ViewPhoneNumberInput { plans = result });//So that you don't need to change the model in the view and the parameter type in the HttpPost Action.
        }

        [HttpPost]
        public IActionResult SecIndex(Plan.API.Models.ViewPhoneNumberInput phoneNumberInput)
        {
            try
            {

                if (ModelState.IsValid)
                {
                    _logger.Log(LogLevel.Information, "User successfully entered their phone number.");
                    return RedirectToAction("FinalIndex", "Final");
                }
                else
                {
                    _logger.Log(LogLevel.Error, "User missed to enter their phone number");
                    throw new Exception("User did not enter a phone number in the textfield!");
                }
             
            }
            catch(Exception ex)
            {
                _logger.LogError(ex, "Empty textfield!");
                return View(phoneNumberInput);
            }
        }

SecIndex.cshtml

@model Plan.API.Models.ViewPhoneNumberInput

<h2>Second page</h2>


@using (Html.BeginForm())
{

    for (int i = 0; i < Model.plans.Count; i++)
    {
        <input type="checkbox" id="@Model.plans[i].PlanId" />
        <input hidden value="@Model.plans[i].PlanId" />
        <input hidden value="@Model.plans[i].PlanName" />

        <label for="Model.plans[i].PlanId"> @Model.plans[i].PlanName </label>
        <br />
    }


    @Html.TextBoxFor(r => r.PhoneNumber)
    <input id="Button" type="submit" value="Next" />

    <p>  @Html.ValidationMessageFor(r => r.PhoneNumber) </p>

}
<script>
    $('form').submit(function () {
        var count = 0;
        $('input[type=checkbox]').each(function () {
            if (this.checked) {
                this.nextElementSibling.name = "plans["+count+"].PlanId";
                this.nextElementSibling.nextElementSibling.name = "plans[" + count + "].PlanName";
                count++;
            }
        });
    });
</script>

我的 API GetPlan 控制器:

        [HttpGet]
        [Route("AvailablePlans")]
        public List<Plans> GetPlan()
        {

            var _model = new ViewPhoneNumberInput();
            _model.plans = new List<Plans>();

            _model.plans.Add(new Plans { PlanId = 1, PlanName = "Internet" });
            _model.plans.Add(new Plans { PlanId = 2, PlanName = "TV & Streaming" });
            _model.plans.Add(new Plans { PlanId = 3, PlanName = "Mobile" });
            _model.plans.Add(new Plans { PlanId = 4, PlanName = "Home Security" });
            _model.plans.Add(new Plans { PlanId = 5, PlanName = "Home Phone" });


            var plansAvailable = JsonSerializer.Serialize(_model.plans);
            _logger.Log(LogLevel.Information, "Response-Body: {@Response-Body}", plansAvailable);


            return _model.plans;
        }

@MarCo 问题是你没有通过你的模式

return View(result);

这是一个工作演示:

api方法:

[HttpGet]
        [Route("AvailablePlans")]
        public List<Plan.API.Models.Plans> GetPlan()
        {

            var _model = new ViewPhoneNumberInput();
            _model.plans = new List<Plans>();

            _model.plans.Add(new Plans { PlanId = 1, PlanName = "Internet" });
            _model.plans.Add(new Plans { PlanId = 2, PlanName = "TV & Streaming" });
            _model.plans.Add(new Plans { PlanId = 3, PlanName = "Mobile" });
            _model.plans.Add(new Plans { PlanId = 4, PlanName = "Home Security" });
            _model.plans.Add(new Plans { PlanId = 5, PlanName = "Home Phone" });


            var plansAvailable = JsonSerializer.Serialize(_model.plans);
            _logger.Log(LogLevel.Information, "Response-Body: {@Response-Body}", plansAvailable);


            return _model.plans;
        }

控制器动作:

public IActionResult SecIndex()
    {
        // call planapi
        var result = _planServiceClient.RetrievePlans().Result;
        _logger.Log(LogLevel.Information, "Reached the Second Page View....");
        return View(new ViewPhoneNumberInput {  plans=result});//So that you don't need to change the model in the view and the parameter type in the HttpPost Action.
    }

查看:

@model Plan.API.Models.ViewPhoneNumberInput


<h2>Second page</h2>
@using (Html.BeginForm())
{

    for (int i = 0; i < Model.plans.Count; i++)
    {
        <input type="checkbox" id="@Model.plans[i].PlanId" />
        <input hidden value="@Model.plans[i].PlanId"/>
        <input hidden value="@Model.plans[i].PlanName" />

        <label for="Model.plans[i].PlanId"> @Model.plans[i].PlanName </label>
        <br />
    }


    @Html.TextBoxFor(r => r.PhoneNumber)
    <input id="Button" type="submit" value="Next" />

    <p>  @Html.ValidationMessageFor(r => r.PhoneNumber) </p>

}
<script>
    $('form').submit(function () {
        var count = 0;
        $('input[type=checkbox]').each(function () {
            if (this.checked) {
                this.nextElementSibling.name = "plans["+count+"].PlanId";
                this.nextElementSibling.nextElementSibling.name = "plans[" + count + "].PlanName";
                count++;
            }
        });
    });
    </script>

结果: