Reputation: 166
I have two classes:
public class Sportevent
{
public int ID { get; set; }
public DateTime EventsStart { get; set; }
public DateTime EventsEnd { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int ID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public int PostalCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Nation { get; set; }
}
So a Sportevent references an Address Entity. The view for creating a Sportevent contains also the forms for the address. The controller receives the infos, but what happens with the Address? How can I pass them or is it already contained
public ActionResult Create([Bind(Include = "EventsStart,EventsEnd, Address")] Sportevent sportevent){
...
}
I think the above syntax of the binding is incorrect, because Address is a complex datatype instead a primitve one, or not? So what's the best practice for passing such complex datamodels?
Upvotes: 0
Views: 313
Reputation: 9463
The Bind
attribute might be necessary as a security precaution if you are binding directly to the EF persistable classes.
To get rid of it, introduce ViewModels that only contain the fields that the user is allowed to change. An additional benefit is that you can put View-centric properties and methods in the ViewModel and they will not pollute your entity model (separation of concerns).
public class CreateSporteventViewModel
{
// ID is not needed in create usecase because it will be assigned by EF
public DateTime EventsStart { get; set; }
public DateTime EventsEnd { get; set; }
public CreateAddressViewModel Address { get; set; }
}
public class CreateAddressViewModel
{
// ID is not needed in create usecase because it will be assigned by EF
// Example of View-centric attribute
[Display(ResourceType = typeof(Resources), Name = "Street")]
public string Address1 { get; set; }
// ... other properties relevant for create view
}
In the View, render the <input>
as mentioned by user7405157:
@model CreateSporteventViewModel
@Html.EditorFor(m => m.EventsStart)
@Html.EditorFor(m => m.Address.Address1)
In the controller, create the entity model and populate it. There are libraries to facilitate this mapping step, e.g. AutoMapper.
public ActionResult Create(CreateSporteventViewModel viewModel){
var persistableEvent = new Sportevent {
EventsStart = viewModel.EventsStart,
// ...
};
var persistableAddress = new Address {
Address1 = viewModel.Address.Address1,
// ...
};
persistableEvent.Address = persistableAddress;
dbContext.Sportevents.Add(persistableEvent);
dbContext.SaveChanges();
}
Upvotes: 1
Reputation: 21
You don't need that Bind
attribute at all.
Just in your view for inputs that should bind the data for Address
in input's name attribute put Address.ID
, Address.Address1
, Address.PostalCode
and so on. Default binding will do the work for you.
Upvotes: 2