0

I am using MVC in a .NET Core 2 web app. I have an entity Schedule that contains meeting schedules between Counselor and Student (both are entities). In my Edit ViewModel for my Schedule I have a property for Counselor and Student - I use this for display only - to display their names and other info on the Schedule I am editing. I am using CounselorId and StudentId in my Schedule object itself. On my HttpGet Action for Edit I am populating my ViewModel just fine with the Counselor and Student. However, on the HttpPost Action of Edit I pass in my ViewModel and I see that my Counselor and Student are both NULL. I then get an error when trying to update my Schedule object. Here is the message:

The association between entity types 'Student' and 'Schedule' has been severed but the foreign key for this relationship cannot be set to null. If the dependent entity should be deleted, then setup the relationship to use cascade deletes.

I found that if I hit the database to populate my model.Counselor and model.Student in my HttpPost Edit Action before I call update that it works. I want to know what the real fix is here using the best practice. Thanks for your help.

Here is my View:

@using CounselorSchedule.ViewModels
@model ScheduleEditViewModel

@{
    ViewData["Title"] = "Edit Schedule";
}

<link href="~/css/bootstrap-datepicker.css" rel="stylesheet" />
@section Scripts{
    <script src="~/scripts/boostrap-datepicker.min.js"></script>

    <script>
        $(document).ready(function () {
            $(".datepicker").datepicker({ format: 'mm/dd/yyyy', autoclose: true, todayBtn: 'linked' })
        });
    </script>
}

<div class="row top-buffer">
    <div class="col-sm-12">
        <h2>Edit Schedule</h2>
    </div>
</div>

<form asp-action="Edit">

    <div class="row top-buffer">
        <div class="col-sm-12">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        </div>
    </div>

    <div class="row">
        <div class="col-sm-12">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <div class="row">
                        <div class="col-sm-4">
                            <h4>Schedule</h4>
                        </div>
                    </div>
                </div>
                <div class="panel-body">
                    <div class="row">
                        <div class="form-group">
                            <div class="col-sm-6">
                                <div class="editor-label">
                                    <input type="hidden" asp-for="ScheduleId" />
                                    <input type="hidden" asp-for="CounselorId" />
                                    <input type="hidden" asp-for="StudentId" />
                                    <label asp-for="Counselor" class="control-label"></label>
                                </div>
                                <div class="editor-field">
                                    @Html.DisplayFor(model => model.Counselor.CounselorFirstName) @Html.DisplayFor(model => model.Counselor.CounselorLastName)
                                </div>
                            </div>
                            <div class="col-sm-6">
                                <div class="editor-label">
                                    <label asp-for="Student" class="control-label"></label>
                                </div>
                                <div class="editor-field">
                                    @Html.DisplayFor(model => model.Student.StudentFirstName) @Html.DisplayFor(model => model.Student.StudentLastName)
                                </div>
                            </div>                            
                        </div>
                    </div>
                    <div class="divide20"></div>                    
                    <div class="row">
                        <div class="form-group">
                            <div class="col-sm-4">
                                <div class="editor-label">
                                    <label asp-for="ScheduleDate" class="control-label"></label>
                                </div>
                                <div class="editor-field">
                                    <input asp-for="ScheduleDate" class="form-control datepicker" type="text" />
                                    <span asp-validation-for="ScheduleDate" class="text-danger"></span>
                                </div>
                            </div>
                            <div class="col-sm-4">
                                <div class="editor-label">
                                    <label asp-for="ScheduleTimeId" class="control-label"></label>
                                </div>
                                <div class="editor-field">
                                    <select asp-for="ScheduleTimeId" class="form-control"
                                            asp-items="@Model.ScheduleTimeList">
                                        <option value="-1" selected>-</option>
                                    </select>
                                    <span asp-validation-for="ScheduleTimeId" class="text-danger"></span>
                                </div>
                            </div>                            
                        </div>
                    </div>                        
                </div>
                <div class="panel-footer">
                    <div class="row">
                        <div class="col-sm-offset-6 col-sm-3">
                            <a class="btn btn-default btn-block"
                               asp-action="Details" asp-route-id="@Model.ScheduleId">Cancel</a>
                        </div>
                        <div class="col-sm-3">
                            <input type="submit" value="Update Case" class="btn btn-primary btn-block" />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

Here is my controller code:

    [HttpPost]
    public IActionResult Edit(ScheduleEditViewModel model)
    {
        var schedule = _repository.GetScheduleDetails(model.ScheduleId);
        if (ModelState.IsValid)
        {
            #region Allow reset of SelectList to "-"
            //If "-" was selected then set to NULL in database
            var scheduleTimeId = Convert.ToInt32(model.ScheduleTimeId);
            if (scheduleTimeId == -1)
                model.ScheduleTimeId = null;
            #endregion                
            Mapper.Map(model, schedule);
            _repository.PutSchedule(schedule);
            return RedirectToAction("Details", "Schedule", new { @id = schedule.ScheduleId });
        }
        else
        {
            model = PopulateScheduleEditViewModel(model, schedule);

            return View(model);
        }
    }

Here is my Edit View Model:

public class ScheduleEditViewModel
{
    public int ScheduleId { get; set; }
    public int CounselorId { get; set; }
    public int StudentId { get; set; }

    [Display(Name = "Counselor")]
    public Counselor Counselor { get; set; }

    [Display(Name = "Student")]
    public Student Student { get; set; }

    [Display(Name = "Schedule Date")]
    [DataType(DataType.Date)]        
    public DateTime? ScheduleDate { get; set; }

    [Display(Name = "Schedule Time")]
    public int? ScheduleTimeId { get; set; }

    public SelectList ScheduleTimeList { get; set; }
}
Rena
  • 30,832
  • 6
  • 37
  • 72
user1778158
  • 95
  • 3
  • 10
  • 1
    Can you show us code of the view and the controller? – Nerevar May 15 '18 at 13:53
  • try use @Html.HiddenFor(m => m.Student.StudentId) in the form. It seems you have a misspell here shoudn't it be ScheduleId? It could also be relevant to see your model. – Nerevar May 15 '18 at 14:25
  • I fixed my typo. I tried adding that and I am getting a bunch of invalid issues on my call to if (ModelState.IsValid) – user1778158 May 15 '18 at 14:36
  • I mean you replaced with @Html.HiddenFor(m => m.Student.StudentId) ? – Nerevar May 15 '18 at 14:38
  • Can you provide the model class? similar issue maybe here : https://stackoverflow.com/questions/11585499/mvc-nested-model-binding-only-partially-working-what-am-i-missing – Nerevar May 15 '18 at 14:39
  • Yes, I did exactly that for StudentId and CounselorId. – user1778158 May 15 '18 at 14:41
  • I think this link could help you also https://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc Your view model should only contain the fields that will actually be edited/displayed, it could be a security breach if the whole model can be edited and throw errors just like the one you have. Simplify the model and do the mapping/wrap up on the controller side. – Nerevar May 15 '18 at 15:25

0 Answers0