I have been dealing with this for at least two days now. I don't have a book available to reference, and I cannot for the life of me find an explanation of how this is supposed to work.
What I am trying to do is a simple operation:
- Load a create form populated with 3 dropdownlist elements which reference other tables
- Fill out the form
- Submit the form and save the entity
I have tried every way I can think of to get this to work. This should be easy. I have tried it with and without a ViewModel. I think it's clearer without the ViewModel
Note: Due to requirements, I am using .NET 3.5. Does this mean I am on an older version of EF?
Another Note: Yes, I am using VB. No, that is not my choice.
Controller:
Function Create() As ActionResult
PopulateForm()
Return View()
End Function
<HttpPost()>
Function Create(ByVal escalation As Escalation) As ActionResult
If TryUpdateModel(escalation) Then
repo.AddEscalation(escalation)
repo.Save()
Return RedirectToAction("Details", New With {.Id = escalation.Id})
End If
'The model did not save - there are validation errors'
PopulateForm()
Return View()
End Function
Private Sub PopulateForm()
ViewData("categoryList") = repo.GetAllCategories().ToList()
ViewData("statusList") = repo.GetAllStatuses().ToList()
ViewData("pathList") = New List(Of Path)
End Sub
Repository:
Public Sub AddEscalation(ByVal esc As Escalation)
esc.Created_At = DateTime.Now()
entities.AddToEscalations(esc)
End Sub
Public Sub Save()
entities.SaveChanges()
End Sub
View:
<div class="editor-label">
<%= Html.LabelFor(Function(model) model.Status)%>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(Function(model) model.Status, New SelectList(ViewData("statusList"), "Id", "Name"))%>
<%= Html.ValidationMessageFor(Function(model) model.Status)%>
</div>
<div class="editor-label">
<%= Html.LabelFor(Function(model) model.Category)%>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(Function(model) model.Category, New SelectList(ViewData("categoryList"), "Id", "Name"))%>
<%= Html.ValidationMessageFor(Function(model) model.Category)%>
</div>
When using the DropDownListFor... model.Property, it fails in the TryUpdateModel call. The validation errors look like this in the returned form: The value '35' is invalid.
If I change it to DropDownListFor...model.Property.Id, it dies on SaveChanges() like so:
Cannot insert the value NULL into column 'Name',
table 'Escalations_Dev.dbo.Categories';
column does not allow nulls. INSERT fails.
The statement has been terminated.
In debugging, my Escalation does have a Category, with only the Id property populated and in the Detached state.
If I do the following to populate the full objects:
Public Sub AddEscalation(ByRef esc As Escalation)
esc.Created_At = DateTime.Now()
esc.Category = Me.GetCategory(esc.Category.Id)
esc.Status = Me.GetStatus(esc.Status.Id)
esc.Path = Me.GetPath(esc.Path.Id)
entities.AddToEscalations(esc)
End Sub
Public Function GetPath(ByVal id As Integer) As Path
Dim path As Path = entities.Paths.FirstOrDefault(Function(c) c.Id = id)
path.CategoryReference.Load()
Return path
End Function
I get: Entities in 'Escalations_Conn.Paths' participate in the 'FK_Paths_Categories' relationship. 0 related 'Category' were found. 1 'Category' is expected.
I really appreciate any help anyone has.