This is taken from VS Add New Scaffolded Item... when creating a new controller.
In the controller:
// GET: Drivers/Create
public ActionResult Create()
{
ViewBag.Tenant = new SelectList(db.Tenants, "TenantID", "TenantName");
return View();
}
The view then renders a drop-down list:
#Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { #class = "form-control" })
The relevant model information:
public partial class Driver
{
public int DriverID { get; set; }
public int Tenant { get; set; }
public virtual Tenant Tenant1 { get; set; }
}
public partial class Tenant
{
public Tenant()
{
this.Drivers = new HashSet<Driver>();
}
public int TenantID { get; set; }
public string TenantName { get; set; }
public virtual ICollection<Driver> Drivers { get; set; }
}
Can someone explain why this works?
I looked at other questions and documentation and couldn't find the answer. I suspect it is something along the lines of "convention over configuration" and it is pulling from the ViewBag using the name of the property. In fact, I changed the ViewBag property to Tenantz and got the following exception:
There is no ViewData item of type 'IEnumerable' that
has the key 'Tenant'.
So is setting the property name of the ViewBag the same as the model property you want to update a good practice? It seems ok but I always hear how you should avoid ViewBag and dynamic types.
As you have already discovered there's a convention. The following line in your view:
#Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { #class = "form-control" })
is exactly the same as this line:
#Html.DropDownList("Tenant", null, htmlAttributes: new { #class = "form-control" })
Now if you look at how the DropDownList helper is implemented in the source code you will notice that it simply does that:
object obj = htmlHelper.ViewData.Eval(name) as IEnumerable<SelectListItem>;
where name is the first argument passed to the DropDownList helper. And guess what? It discovers the corresponding value that you have set in your controller: ViewBag.Tenant = ....
This being said using ViewBag is an absolutely, disastrously, terribly bad practice. You've already find out why. It can bite you like a dog without you even knowing what's going on. The best way to protect against those dogs (ViewBag) is to search them inside your solution and give them poison. Simply get rid of absolutely any ViewBag calls in your code and use view models. Then you will not get bad surprises and everything will have a reasonable explanation and questions like this wouldn't be necessary on StackOverflow.
Like for example you could write a normal view model:
public class DriverViewModel
{
public int? SelectedTenantID { get; set; }
public IEnumerable<SelectListItem> Tenants { get; set; }
}
and a normal controller action that will query your datastore for the required information and project your entity model to the view model:
// GET: Drivers/Create
public ActionResult Create()
{
var viewModel = new DriverViewModel();
viewModel.Tenants = new SelectList(db.Tenants, "TenantID", "TenantName");
return View(viewModel);
}
and finally the corresponding strongly typed view:
#model DriverViewModel
...
#Html.DropDownListFor(
model => model.SelectedTenantID,
Model.Tenants,
htmlAttributes: new { #class = "form-control" }
)
In this case you are using a strongly typed view, with a strongly typed view model and a helper. There are no longer any doubts (and dogs that bite). The code is readable and you cannot ask, why this convention over configuration is doing this or that. So as long as there's no trace of ViewBag in your application there will be no such questions.
Related
I'm new in mvc and I try to create a simple page with table and ajax search.
For example, I have a search model, which pass parameters from form to controller.
Model:
public class OrderSearchViewModel
{
[Display(ResourceType = typeof(Lang), Name = "OrderID")]
public int? OrderID { get; set; }
[Display(ResourceType = typeof(Lang), Name = "DeliveryType")]
public int? DeliveryTypeID { get; set; }
[Display(ResourceType = typeof(Lang), Name = "Partner")]
public string CustomerName { get; set; }
public SelectList DeliveryTypes { get; set; }
}
In controller I have an action witch return View with form:
public ActionResult Index()
{
var ordersSearchModel = // default init;
return View(model);
}
In my Index.cshtml I have a form
#model Models.Order.OrderSearchViewModel
<div class="row">
#using (Ajax.BeginForm("Orders", "Order", new AjaxOptions {UpdateTargetId = "ordersList"}, new {#id = "searchForm", #class = "form-horizontal"}))
{
// Editors templates for each params
}
</div>
<div id="ordersList" class="row">
</div>
}
In my Controller I have a method, witch take search model and return a partial view
[HttpPost]
public async Task<ActionResult> Orders(OrderSearchViewModel model, int page = 1, int pageSize = 50)
{
var models = // connect to db and get data filtered by model params
return PartilaView("_View", models);
}
In result partial I have a table with order num and link to edit view.
In edit view I have a link back to search:
#Html.ActionLink("Back", "Index", "Order", new { #class = "btn btn-default" })
And by click this link I get the Index view in default (without search parameters) and user must fill it once again.
What will be the best practice to remember user search parameters?
Thanks for any advice.
As devqon said, the preferred approach is to use query parameters, but it does sound like your usage might make this a bit difficult to manage
TempData/SessionData may solve your issue, but using this approach will cause problems if the user decides to use your application in multiple tabs/windows (they will all share the same search params)
Something that might be worth looking into is SessionStorage.(Link below)
This type of storage persists as long as the browser stays open
And importantly
Opening a page in a new tab or window will cause a new session to be initiated
So your pages shouldn't share state.
More details here:
https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
Hi i have three Fields in my view.That three fields are drop down. I want to pass the value to these fields when edit button is clicked. That is the values need to pass to that drop down fields. My view is mentioned below
In my view i have many drop downs but once i know how to pass the value to one drop down means i will do for another drop downs.
For Edit i create one view in sql and connect that view as EDMX file in my application.In this view(table) i have all fields which is in Visitors Form. That view name is View_VisitorsForm.
My Model(VisitorsViewModel)
public Nullable<System.DateTime> Date { get; set; }
public System.Guid VisitingID { get; set; }
public Nullable<System.Guid> EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string Description { get; set; }
My Edit Code
public ActionResult Edit(Guid ?id)
{
WafeERPNEWEntities db = new WafeERPNEWEntities();
SelectList typelist = new SelectList(db.Employees.ToList(), "EmployeeID", "DisplayName", db.Employees);
ViewData["EmployeeName"] = typelist;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
VisitorsViewModel ObjVisitorsviewModel = new VisitorsViewModel();
View_VisitorsForm visit = db.View_VisitorsForm.Find(id);
visit.VisitingID = ObjVisitorsviewModel.VisitingID;
visit.VisitingDate = ObjVisitorsviewModel.Date;
visit.Description = ObjVisitorsviewModel.Description;
if (ObjVisitorsviewModel == null)
{
return HttpNotFound();
}
return View(ObjVisitorsviewModel);
}
My View Code
#Html.LabelFor(model => model.Date)
#Html.EditorFor(model => model.Date)
#Html.ValidationMessageFor(model => model.Date)
#Html.LabelFor(model => model.VisitingID)
#Html.EditorFor(model => model.VisitingID)
#Html.ValidationMessageFor(model => model.VisitingID)
#Html.LabelFor(model => model.EmployeeName)
#Html.DropDownList("EmployeeID", (IEnumerable<SelectListItem>)ViewData["EmployeeName"])
#Html.ValidationMessageFor(model => model.EmployeeName)
Now when i click the edit button it pass the value to this line
View_VisitorsForm visit = db.View_VisitorsForm.Find(id);
and also it getting visit.visitingID. But it is not getting the value in viewmodel .so the value will be empty in view.All values are empty VisitingID, Description, Date Fields are empty and in Employee drop down it won't show the value which i passed to this field it shows the first value in dropdown. so please any one tell me how to solve this issue. Actually I try to explain my issue as per my level best and if you didn't understand my issue or any one need my full code or need more code tell me . i ready to update my code again. but i need solution.
Advance Thanks..
use:
#Html.DropDownListFor(model => model.EmployeeID,(IEnumerable<SelectListItem>)ViewData["EmployeeName"])
The important part being "DropDownListFor". You are using "DropDownList".
Use the DropDownListFor helper method.
#Html.DropDownListFor(model => model.EmployeeID,
(IEnumerable<SelectListItem>)ViewData["EmployeeName"])
Now in your GET action, you need to set the EmployeeID property value of your view model.
public ActionResult Edit(int id)
{
var objVisitorsviewModel = new VisitorsViewModel();
// I am hard coding to 25.
// You may replace it with a valid Employee Id from your db table for the record
ObjVisitorsviewModel.EmployeeID= 25;
return View(objVisitorsviewModel);
}
A more clean solution is to not use ViewData to transfer the data you need to render the dropdown option. You can make your code more strongly typed by simply adding a new property to your view model
public class VisitorsViewModel
{
public List<SelectListItem> Employees { set;get;}
public Guid? EmployeeID { get; set; }
// Your existing properties goes here
}
Now in your GET action(create/edit), Instead of storing the data in ViewData, we will load to the Empenter code hereloyees property.
public ActionResult Edit(int id)
{
var vm = new VisitorsViewModel();
vm.Employees = db.Employees.Select(s=> new SelectListItem {
Value=s.EmployeId.ToString(), Text=s.DisplayName }).ToList();
return View(vm);
}
And in your view, we will use the DropDownListFor helper method with the Employees property
#model VisitorsViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(s=>s.EmployeeID,Model.Employees,"Select")
}
You are using a DropDownList(...) instead of a DropDownListFor(...)
Your Model
You must add a SelectList:
public SelectList Employees { get; set }
Your Edit
You must get your employees list and add it to your model:
// Get employees list from the database
var employees = db.Employee.Select(x => x.Id, x.Name).Tolist();
// Put the employees in a SelectList
var selectList = new SelectList(employees .Select(x => new { value = x.Id, text = x.Name }), "value", "text");}).ToList();
// Pass the list to your ViewModel
ObjVisitorsviewModel.Employees = selectList;
Your View
Finally, change your DropDownListFor line for this:
#Html.DropDownListFor(model => model.EmployeeID,
model.Employees)
By using DropDownList(...), your object data is not bound to the DropDown. You must manage its selected value manually.
I'm just picking up .net MVC and I've come across something that I can't work out. I'm obviously missing some basic principle but would love some help.
I have a ViewModel with two IEnumerables that I want to use to create dropdownlistfors. My GET works fine, the lists are populated as expected.
Now I'm posting the ViewModel back to a POST method, not to do anything useful but just to try and understand how mvc works. I expected that I would simply be able to re-populate the dropdownlistfors from the model that was posted back - but I get a null reference exception.
Other values, such as partyid, in the ViewModel survive the POST so i'm confused.
I can get it to work if I repopulate the lists but that seems wrong.
Can someone give me a pointer?
My ViewModel
public class DemoViewModel
{
//properties
public IEnumerable<tbl_server_lookup> servers { get; set; }
public int serverId { get; set; }
public IEnumerable<tbl_site_lookup> sites { get; set; }
public int siteId { get; set; }
public int partyid { get; set; }
public string message { get; set; }
public DemoViewModel()
{
}
}
My Controller
// GET: /Demos/Test/
[HttpGet]
public ActionResult Test()
{
DemoViewModel demo = new DemoViewModel();
using (var dbContext = new ADAPI.Models.db_ad_apiEntities2())
{
var serverList = dbContext.tbl_server_lookup.Where(s => s.server_name != null);
demo.servers = serverList.ToList();
var siteList = dbContext.tbl_site_lookup.Where(w => w.site_name != null);
demo.sites = siteList.ToList();
}
demo.message = "Enter the user id you would like to look up in the box below.";
return View(demo);
}
//
//POST: /Demos/Test/
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(DemoViewModel demo)
{
//It works if I uncomment this block...
/*using (var dbContext = new ADAPI.Models.db_ad_apiEntities2())
{
var myQuery = dbContext.tbl_server_lookup.Where(s => s.server_name != null);
demo.servers = myQuery.ToList();
var siteList = dbContext.tbl_site_lookup.Where(w => w.site_name != null);
demo.sites = siteList.ToList();
}*/
demo.message = "the user id you posted is: " + demo.partyid + ". The Server you selected is: ";// +demo.serverId;
return View(demo);
}
My View
#model ADAPI.ViewModels.DemoViewModel
<h2>Demos</h2>
<h3>#Model.message</h3>
#using (Html.BeginForm("Test","Demos"))
{
#Html.AntiForgeryToken()
<div class="">
<h4>Party ID</h4>
#Html.ValidationSummary(true)
<!-- input box for party id-->
#Html.TextBoxFor(model => model.partyid)
<!-- dropdown list of server types eg live vs test-->
#Html.DropDownListFor(model => model.serverId, new SelectList(Model.servers, "server_Id","server_name"))
#Html.DropDownListFor(model => model.siteId, new SelectList(Model.sites, "site_short_name","site_name"))
<input type="submit" value="Try" />
</div>
}
The Error
In MVC, model on the views are loaded in the controller action, they are not posted back along with the post action.
If you are used to ASPX's viewstate, there is no such thing in MVC, you need to load what you need for every view in the current action.
Dropdown lists are rendered into html as tag and returned to the server as plain single value.
You have to rebind/repopulate them on the server, wchich is annoying in scenarios like validation, where the same model should be returned to the client.
There is no support for that in the framework - you have to do it on your own.
One more thing - if you absolutely have to return the list items and want them back on the server, you can serialize tham and hide in some hidden field. But it's ugly and unsecure since anyone can change its value.
I'm working on an EntityFramework project and running into an interesting problem. What I want to do is create a database entity using a view, but in order to do that I need to create another database entity of a different type that the first entity needs to be associated with, and I'm trying to do this from the same view.
For example, we have a Person, and each Person will have a recurring appointment. However, appointments can be recurring on different types of criteria. Right now I'm trying to get this working on appointments that will be on a daily basis (meaning, for example, every Monday, Wednesday, and Friday) So here, my model is something like:
DailyAppointment implements the abstract class AppointmentFrequency
Person has an AppointmentFrequency associated with it. Here is the code behind my model (database generated using code-first migrations).
AppointmentFrequency :
public abstract class AppointmentFrequency
{
[KeyAttribute]
public int Identity { get; set; }
}
DailyAppointment :
public class DailyAppointment : AppointmentFrequency
{
public bool Monday { get; set; }
// ... Variable for each day of the week.
}
Person:
public class Person
{
[Key]
public int Identity { get; set; }
//... Other information
[ForeignKey("AppointmentFrequency_Identity")]
public virtual AppointmentFrequency AppointmentFrequency { get; set; }
public int? AppointmentFrequency_Identity { get; set; }
}
So in our view, when we create a Person, we want to have an AppointmentFrequency associated with them.
Currently, my approach involves a partial view inside the view that creates a Person:
#using (Html.BeginForm("AddPerson", "ControllerName", FormMethod.Post, new { role = "form", #class = "form-inline" }))
{
... //This is where we get information about the Person
Model.Person.AppointmentFrequency = new DailyAppointment();
var dailyAppointment = Model.Person.AppointmentFrequency as DailyAppointment;
if (dailyFrequency != null)
{
#Html.Partial("_DailyAppointmentEditor", Model.Person.AppointmentFrequency as DailyAppointment);
}
<div class="form-group">
<button class="btn btn-primary" type="submit">Add</button>
</div>
}
(I have also tried doing this a few similar ways, such as sending the dailyAppointment variable into the partial view instead)
My partial view looks like this:
#model Database.Entities.DailyAppointment
#Html.LabelFor(model => model.Monday)
#Html.CheckBoxFor(model => model.Monday, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Monday, null, new { #class = "text-danger" })
#Html.LabelFor(model => model.Tuesday)
#Html.CheckBoxFor(model => model.Tuesday, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Tuesday, null, new { #class = "text-danger" })
... //The rest of the days and script bundling
Inside my controller, I am only creating a Person, and was hoping that the Appointment would be created by the Framework, but that doesn't seem to be the case.
[HttpPost]
public ActionResult AddPerson(Person person){
this.db.People.AddOrUpdate(person);
this.db.SaveChanges();
return this.View();
}
I know one way of doing this would be to collect the data and then use it in the form post sent to the controller, creating the frequency, and then adding the reference to the person object and creating it in the database. I have actually done that and know that it works, but I feel like there must be a more friendly way of doing this within the framework.
Part of the challenge here is that I'm hoping to make this extensible while still using the same design. Let me know if I can give any more information, but if you have any suggestions for this approach or for a different approach I can take, I would greatly appreciate it! Thank you.
I've looked, tried several different solutions and haven't found anything that works (at least, not something with an example close enough to what I want for me to follow). I'm sure I'm missing something that would be a simple thing to a more experienced coder. Help?
I have a Model called Residents. It includes ResidentID, PFName, PLName. I have a controller for Residents. I have CRUD views for Residents. All working just fine.
I have a Model called Logs. It includes LogID, ResidentID, Comments. I have a controller for Logs. I have CRUD views for Logs. All working just fine.
I can display all the log entries for a Resident. Works fine. After a Log entry has been created, I can display the PFName using the method
#Html.DisplayFor(model => model.Resident.PFName)
Next, I want to Create a new log entry for a selected Resident.
That's where I'm having the problem. I would like the "Create" view (for the Log) to display the ResidentFName and ResidentLName of the selected resident, not the ResidentID.
A this point, from the Details view for a Resident, I have a CreateLog link.
#Html.ActionLink("New Log Entry", "../Log/Create", new { #ResidentID = Model.ResidentID})
This (likely not the best way) gives me a URL with the value of the selected ID
http://localhost:999/Log/Create?ResidentID=1
The value for the ResidentID is correct; it changes depending on which Resident is selected.
This value is correctly entered
#Html.TextBoxFor(model => model.ResidentID)
on the new CreateLog page using the Log Controller Create action.
public ActionResult Create(int ResidentID)
I plan to hide the ResidentID TextBox so the user doesn't see it. It seems I have to make it available in the form to be able create a new log entry.
The CreateLog form currently works as I have it now. I can create a log entry and verify that entry has been correctly recorded for the Resident.
But, I would like the form to display the PFName and PLName for the Resident so the user has visible feedback for which Resident was selected.
I believe that the related data (PFName and PLName) I want has to be passed to the CreateLog form .... somehow. I can't get it from the form.
Since there's only the unsaved entry for ResidentID, I can't use the value from the CreateLog form it to display related data. As mentioned, for the Lists, there is no such problem. It's only for CreateLog.
I've tried adding the data to the URL. Not working. I've tried setting the strings in the Controller (and the URL). Not working. I've looked at setting a cookie, but haven't ever done that so not sure what to set or where to put it or how to get the values from it. I've looked at setting a variable in the controller ... (have that working to display drop down lists, but a list to select from is not what I need -- I want the matching values from the related table).
Log.LogID(PK, Identity)
Log.ResidentID(FK)
Resident.PFName
Resident.PLName
I can directly create a view with these tables/fields in my SQLDB and update it.
Assuming a view model which looks something like this:
public class CreateLogViewModel
{
public int ResidentID { get; set; }
public string PFName { get; set; }
public string PLName { get; set; }
public string SomeLogCreationProperty { get; set; }
// other properties
}
Your controller could look something like this:
public ActionResult Create(int ResidentID)
{
var model = db.Residents.Where(r => r.ResidentID == ResidentID)
.Select(r => new CreateLogViewModel
{
ResidentID = r.ResidentID,
PFName = r.PFName,
PLName = r.PLName
// other properties
});
return View(model);
}
Then the view:
#model CreateLogViewModel
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.ResidentID)
#Html.HiddenFor(m => m.PFName)
#Html.HiddenFor(m => m.PLName)
#Html.EditorFor(m => m.SomeLogCreationProperty)
// other properties
<input type="submit" />
}
This would then POST back to:
[HttpPost]
public ActionResult Create(CreateLogViewModel model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
// Redisplay the form with errors
return View(model);
}
Expanding on John H and StuartLC answers, you need to use ViewModels and the following workflow:
Database->(load)->Model->Controller->(convert)->ViewModel->View
and
View->ViewModel->Controller->(convert)->Model->(save)->Database
So lets says you have the following models:
namespace Models
{
public class Residents
{
public int ResidentID { get; set; }
public string PFName { get; set; }
public string PLName { get; set; }
//...
}
public class Logs
{
public int LogID { get; set; }
public int ResidentID { get; set; }
public string Comments { get; set; }
//...
}
}
You need a ViewModel that combines the data you need for display and input in your Log\CreateView:
namespace ViewModels
{
public class ResidentLog
{
public int ResidentID { get; set; }
public string PFName { get; set; }
public string PLName { get; set; }
public string Comments { get; set; }
//...
}
}
Then inside the controller:
public class LogController : Controller
{
[HttpGet]
public ActionResult Create(int ResidentID)
{
// Run in debug and make sure the residentID is the right one
// and the resident exists in the database
var resident = database.Residents.Find(residentID);
var model = new ViewModels.ResidentLog
{
ResidentID = resident.ResidentID,
PFName = resident.PFName,
PLName = resident.PLName,
Comments = string.Empty,
// ...
};
// Run in debug and make sure model is not null and of type ResidentLog
// and has the PFName and PLName
return View(model);
}
[HttpPost]
public ActionResult Create(ViewModels.ResidentLog model)
{
if (!ModelState.IsValid)
return View(model);
var log = new Models.Logs
{
// Assumes LogID gets assigned by database?
ResidentID = model.ResidentID,
Comments = model.Comments,
};
// Run in debug and make sure log has all required fields to save
database.Logs.Add(log);
database.SaveChanges();
return RedirectToAction("Index"); // Or anywhere you want to redirect
}
}
Then your Log\CreateView:
#model ViewModels.ResidentLog
<!-- Display the values needed -->
<div>#Model.ResidentID - #Model.PFName - #Model.PLName</div>
#using (var form = Html.BeginForm(...))
{
<!-- This saves the values for the post, but in fact only ResidentID is actually used in the controller -->
#Html.HiddenFor(m => m.ResidentID)
#Html.HiddenFor(m => m.PFName)
#Html.HiddenFor(m => m.PLName)
#Html.EditorFor(m => m.Comments)
<input type="submit" />
}
You need to provide the additional information to the view.
This can be done in at least 2 ways
Use the ViewBag dynamic as a quick and dirty cheap and cheerful container to pass everything the view needs from the controller.
(preferred) Use a custom ViewModel with a tailor made class which holds everything the view needs. This is generally preferred as it is statically typed.
(I'm assuming that resident is already persisted in the database by the time the Log controller is called - you might need to fetch it elsewhere)
So, in your log controller, here's an example of using ViewBag:
[HttpGet]
public ActionResult Create(int residentID)
{
ViewBag.Resident = Db.Residents.Find(residentId);
return View();
}
You can then show the resident properties on the view by utilizing the ViewBag.
Edit
Yes, by persisted I meant in the Db - apologies about using unclear jargon.
Here's another example of ViewBag approach (the idea is to create a new Comment for another object):
Doing this the cheap + cheesy ViewModel way - in the HTTPGet Controller Create method:
public ActionResult Create(string objectType, int objectId)
{
// This is equivalent to youn fetching your resident and storing in ViewBag
ViewModel.Object = FetchSomeObject(objectType, objectId);
return View();
}
And in the View I use this (The ViewBag is accessible to Controller and View):
<title>#string.Format("Add new Comment for {0} {1}", ViewBag.Object.ObjectType, ViewBag.Object.Name);</title>
As you say, you will also need to do add a hidden for the ResidentId in your create log form
As per #JohnH's answer (+1), the BETTER way to do this (than using the magic ViewBag dynamic) is to create a custom ViewModel specifically for this screen. The ViewModel can either be reused both ways (GET: Controller => View and POST : Browser => Controller, or you even have separate ViewModels for the Get and Post legs.
With much thanks to all, I have it working. The final piece was telling the controller to return the model (nl). Here's the full spec for what's working:
I have created a ViewModel that includes
public class NewLog
{
public int ResidentID { get; set; }
public string PFName { get; set; }
public string PLName { get; set; }
public string Comment { get; set; }
// other properties
}
In the LogController,
public ActionResult Create(int ResidentID)
{
var resident = db.Residents.Find(ResidentID);
var nl = new NewLog
{
ResidentID = ResidentID,
PFName = resident.PFName,
PLName = resident.PLName,
Comment = string.Empty,
};
return View(nl);
}
In the Create.cshtml page,
#model My.Models.NewLog
The required ResidentID to be recorded with the new Log Entry
#Html.TextBoxFor(model => model.ResidentID, new {#Type = "Hidden"})
And the related, user-friendly display boxes for the person's name
#Html.DisplayFor(model => model.PFName)
#Html.DisplayFor(model => model.PLName)
And in the URL which is used to access the create page,
#Html.ActionLink("New Log Entry", "../Log/Create", new { #ResidentID = item.ResidentID, item.PFName, item.PLName})