【问题标题】:Variable contains a null value after selecting checkboxes选中复选框后变量包含空值
【发布时间】:2021-10-11 13:27:36
【问题描述】:

我有两个同时运行的项目,一个 ASP.NET Core MVC 5.0 Web 项目和一个 ASP.NET Core Web API 5.0 项目。选择任何所需复选框并在调试时将数字键入文本框并击中下一步时,我注意到在我的Post Action SecIndex() Methable phoneNumberInput 987654329 @和plansPhoneNumber 将保存我在文本框中输入的值,但 plansnull。我似乎无法理解为什么 plans 应该包含我选择的 null是否有什么原因导致它返回 null 而不是我选择的值?

MVC 项目:

Controller 我在哪里调用我的 API:

public IActionResult SecIndex()
{
    // call planapi
    var result = _planServiceClient.RetrievePlans().Result;
    _logger.Log(LogLevel.Information, "Reached the Second Page View....");
    var x = 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.
    return View(x);
}

[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);
    }
}

RetrievePlans() 致电SecIndex()

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;
}

在 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" />
        <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>

我试图在&lt;script&gt; 内放置一个断点,但断点永远不会被命中。即使我选择了一个值,这可能是plansnull? 的原因吗

然后在 API 项目中:

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; }
}

Plans模型类:

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

Controller 用于 API:

[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;
}

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-core-mvc asp.net-core-webapi


    【解决方案1】:

    下面的代码只包含与 View-Controller 相关的部分。

    Selected 属性被添加到Plan:此更改使视图内容更简单。实际上,在进行这个简单的更改后,无需使用 JavaScript 来处理复选框状态。

    数据模型:

    public class Plan
    {
        public int PlanId { get; set; }
        public string PlanName { get; set; }        
        public bool Selected { get; set; }
    }
    
    public class ViewPhoneNumberInput
    {
        [Required(ErrorMessage = "You did not enter your phone number! Please enter your phone number!")]
        public String PhoneNumber { get; set; }
    
        public List<Plan> Plans { get; set; }
    }
    

    在控制器中:

    public IActionResult SecIndex(ViewPhoneNumberInput model)
    {            
        if ( model == null || model.Plans == null)
        {
            var result = _planServiceClient.RetrievePlans().Result;       
            model = new Plan.API.Models.ViewPhoneNumberInput { Plans = result };
                     
            ModelState.Clear(); 
        }
        return View(model);
    }
    
    [HttpPost]
    public IActionResult Processing(ViewPhoneNumberInput data)
    {
        if (ModelState.IsValid)
        {
            foreach (var plan in data.Plans)            
            {
                if (plan.Selected)
                {
                    /* processing the selected plan */ 
                }                
            }
            return RedirectToAction("FinalIndex", "Final");            
        }
        else
        {
            return View("SecIndex", data);
        }
    }
    

    SecIndex.cshtml

    @model Models.ViewPhoneNumberInput
    
    @{ ViewBag.Title = " "; }
    
    <h2>Store List</h2>
    
    @using (Html.BeginForm("Processing", "Home"))
    {
        for (int i=0; i < Model.Plans.Count; i++)
        {
            <div class="form-group row">
                @Html.CheckBoxFor(r => Model.Plans[i].Selected)          
                <label>  @Model.Plans[i].PlanName</label><br />
    
                @Html.HiddenFor(h => @Model.Plans[i].PlanId)
                @Html.HiddenFor(h => @Model.Plans[i].PlanName)
            </div>
        }
    
        @Html.TextBoxFor(r => Model.PhoneNumber)
        <p>  @Html.ValidationMessageFor(r => Model.PhoneNumber) </p>
    
        <input id="Button" type="submit" value="Next" />    
    }
    

    【讨论】:

    • 谢谢!我实施了您的建议,当我点击 URL /Second/SecIndex 时,我得到了与我预期不同的视图。请检查原帖。你也明白吗?
    • 当你说要在那个部分调用 RetrievePlans 我做了plans = _planServiceClient.RetrievePlans().Result
    • @MarkCo:我在帖子中做了一些修复。尝试应用这些修复。
    • 谢谢!每当我执行ModelState.Clear; 时,它告诉我CS0201:只有赋值、调用、递增、递减、等待和新对象表达式可以用作语句。你也明白了吗?
    • @MarkCo:打字错误:应该是ModelState.Clear();对不起。
    猜你喜欢
    • 1970-01-01
    • 2014-01-03
    • 2015-10-05
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多