asp.net-mvc


Saving entities with foreign key in ASP.NET MVC


I need some help doing something I am assuming is simple. I am using ASP.net MVC 3 with CodeFirst (CTP5)
I have two entities: Company and Location. A Company can many Locations. The classes are as follows (stripped of all needless info)
public class Company
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Location> Locations { get; set; }
}
public class Location
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public virtual Company Company { get; set; }
}
Now in my controller, I only allow creating a Location within the context of a Company, so the Company Id is always passed in (In the View, I show the name of the Company in a read only field, but do not allow the user to change/edit that.
public ActionResult Create(int companyId)
{
Company company = _session.Single<Company>(c => c.Id == companyId);
Location newLocation = new Location {Company = company};
return View(newLocation);
}
[HttpPost]
public ActionResult Create(Location location)
{
if (ModelState.IsValid)
{
_session.Add<Location>(location);
_session.CommitChanges();
return RedirectToAction("Index");
} else {
return View(location);
}
}
Now whenever I try to create a new location, the ModelState.IsValid is always false due to the fact that location.Company.Name is not supplied and is a required field on Company. I am never trying to create a new company here, I merely trying to create a location with a reference to the correct company. I don't want to add the Name property to the view just to get the ModelState to validate. How can this be accomplished easily? Should I be passing something different from the view? or to the view?
As i was explaining in my comment, i stumbled upon a small change which makes this work, still think it is a kludge as I dont see why i need to duplicate the child Id paramater, but the best/simplest one I could find that should be easy to update in the future and I will be the first to admit I dont know all (or most) of what there is in CodeFirst.
I changed the location class from:
public class Location
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public virtual Company Company { get; set; }
}
To:
public class Location
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
}
Now as far as I can tell, this hasnt changed the database schema at all, but now the only thing which is required on the Location (when validating) is that there is an ID in the CompanyId field, the Company property can be left null (before, it was trying to validate a proper Company since the Company class was required).
So now when creating a Location, the only thing the view needs to pass back in the CompanyId.
Anyone see any drawbacks? or a better way?
You can easily just add a hidden field with company name on your form. Its data will get picked up and sent to your POST action as expected.
If you don't use company name on the server side at all, you can fill this hidden field up with any dummy text as long as company ID is correct (because you use it). But if you do need correct company name with your ID, you'll have to fill actual name into hidden field instead of some dummy text.
Anyway. This will add a hidden field for your company name
<%= Html.HiddenFor(m => m.Company.Name) %>
and if you don't have your Company property set to anything then, you can as well use this:
<%= Html.Hidden("Company.Name", "Super duper company") %>
Whether this value is an actual name or a dummy name it doesn't really matter. Your model will be valid upon postback.
Regular postback or Ajax?
I suppose you're using a regular postback and not an Ajax postback. If you do use Ajax one and you're using jQuery and calling $.post() or $.ajax() or something similar, you can always provide whatever object you like. You can fill any value for the company name in your JavaScript code.
If you have complex objects in JavaScript and would like to send them to your controller action with strong type parameters (so they will be validated) you can use this little jQuery plugin of mine, that prepares any JSON object to be correctly sent to Asp.net MVC action so data will be automatically data bound to your strong types to get validated. Does JavaScript dates as well. :)
Additional information
Since you pointed out (in a comment) that your entities are very much work in progress and you may be adding/removing required fields, this may be very tedious to also change all related views.
Yet there are ways you may take, to make your life a bit easier when it comes to changable models and different validation scenarios depending on object state:
Have separate view models for creation process that also include functionality to auto-convert to application model class:
public class LocationCreate
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int CompanyId { get; set; }
public Location ToModelInstance()
{
return new Location {
Id = this.Id,
Name = this.Name,
Company = new Company {
Id = this.CompanyId,
Name = "Super duper company Ltd." // you can as well omit this line
}
};
}
}
Use inheritance:
public class CompanyBase
{
public int Id { get; set; }
}
public class Company : CompanyBase
{
[Required]
public string Name { get; set; }
public virtual ICollection<Location> Locations { get; set; }
}
public class Location
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public virtual CompanyBase Company { get; set; }
}

Related Links

EF Core + MVC 6 + .NET Core RC2 - EF not returning results
Can we display linq result in view without using model
EF - work with universal entity in library project, when not specified database entities
asp.net core not detecting classlibrary Model on View during runtime
Using Ajax.BeginForm helper in MVC 5 for uploading picture issue [duplicate]
Decorating class with Authorize assumes Office 365 login, instead of offering choice
how can pass the parametrized ActionResult value through ActionLink()
How to get HtmlHelper.Action() working inside a webforms aspx page
Session variables in MVC 5
Azure web apps life cycle
RequiredIf for RadioButtonFor [duplicate]
Whenever use Refresh token In Web API?
How do you secure static (HTML/css) content on an azure webapp virtual directory?
Scientific value is displaying ,while export data from GridView in MVC
MVC View Does Not Contain Expected Data
Sitecore / ASP.NET Request Validation Won't Disable

Categories

HOME
flutter
odoo-10
identityserver4
xaml
dicom
load
order
xamarin.forms-listview
vsix
build.gradle
jfreechart
add-in
identifier
square-connect
doorkeeper
sql-server-express
jscrollpane
numericupdown
ellipse
python-2.5
prerender
h.264
exe4j
smartcard
jmeter-plugins
cayley
code-analysis
spark-graphx
rgdal
core-location
bitcode
precision
slf4j
angular-services
jtable
desire2learn
icloud-drive
desktop-app-converter
regex-group
x-sendfile
webfocus
asp.net-identity-2
temp
ocean
pymysql
tensor
double-click-advertising
mask
powerbuilder-conversion
tibco-ems
logicblox
project-centennial
spark-submit
mobile-browser
appdynamics
clientscript
manifoldjs
wrk
mrtg
unityscript
hipi
netbeans-7
android-camera-intent
wxhaskell
configuration-profile
vispy
business-logic
kernighan-and-ritchie
webdeploy-3.5
geneos
cover
groupbox
sliding
pddl
ctakes
lidar
par
cng
phone-number
pyenchant
base-conversion
abort
android-print-framework
size-t
iife
setattribute
mklink
gdk
linguistics
syndication-feed
email-spam
jquery-backstretch
mydbr
populate
mongo-shell
batman.js
ccombobox
geometry-surface
arbtt
html5-apps
cassette
timestamp-with-timezone
noindex
b-method
katta
duplicate-data
ramaze
openfeint
machine.config
scramble
greensoftware
versant-vod

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App