问题
I have an object named Visit
and i defined the following helper method
(“CanBeEdited”) to specify if users can edit the object Status
property or not:-
public partial class Visit
{
public bool CanBeEdited(string username)
{return (((DoctorID != null) && (DoctorID.ToUpper().Equals(username.ToUpper()))) && (StatusID == 5)); } }}
Then i have specified to show or hide certain dropdownlist
on my Edit
view depending on weather the CanBeEdited
helper method returns true or false (if it returns true then the user can view and edit the Status dropdownlist
, and if it returns false then the view will render an @Html.HiddenFor
representing the old status value).
My edit view which includes the helper method looks as following:-
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Visit</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Note)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Note)
@Html.ValidationMessageFor(model => model.Note)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.DoctorID)
</div>
<div class="editor-field">
@Html.DropDownList("DoctorID", String.Empty)
@Html.ValidationMessageFor(model => model.DoctorID)
</div>
@{
if (Model.CanBeEdited(Context.User.Identity.Name))
{
<div class="editor-label">
@Html.LabelFor(model => model.StatusID)
</div>
<div class="editor-field">
@Html.DropDownList("StatusID", String.Empty)
@Html.ValidationMessageFor(model => model.StatusID)
</div>
}
else
{
@Html.HiddenFor(model => model.StatusID)}
}
<p>
@Html.HiddenFor(model => model.VisitTypeID)
@Html.HiddenFor(model => model.CreatedBy)
@Html.HiddenFor(model => model.Date)
@Html.HiddenFor(model => model.VisitID)
@Html.HiddenFor(model => model.PatientID)
@Html.HiddenFor(model => model.timestamp)
<input type="submit" value="Create" />
</p>
</fieldset>
}
To be honest it is the first time i implement such as case,, so is my approach sound valid ???,, or it have some weaknesses i am unaware of ??. As i need to implemented similar cases all around my web application...
Baring in mind that i am also checking for the CanBeEdited on the action methods..
Thanks in advance for any help.
Updated:- My post action method look as follow:-
[HttpPost]
public ActionResult Edit(Visit visit)
{
if (!(visit.Editable(User.Identity.Name)))
{
return View("NotFound");
}
try
{
if (ModelState.IsValid)
{
repository.UpdateVisit(visit);
repository.Save();
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (Visit)entry.Entity;
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
// patient.timestamp = databaseValues.timestamp;
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}
ViewBag.DoctorID = new SelectList(Membership.GetAllUsers(), "Username", "Username", visit.DoctorID);
ViewBag.StatusID = new SelectList(db.VisitStatus, "StatusID", "Description", visit.StatusID);
ViewBag.VisitTypeID = new SelectList(db.VisitTypes, "VisitTypeID", "Description", visit.VisitTypeID);
return View(visit);
}
回答1:
I don't feel adding that in the View is a good idea. I would like to have My ViewModel to hold a property of boolean type to determine that it is editable or not. The value of that you can set in your controller after checking the relevant permissions.
public class ProductViewModel
{
public bool IsEditable { set;get;}
//other relevant properties
}
and controller action
public ActionResult GetProduct()
{
ProductViewModel objVM=new ProductViewModel();
objVm.IsEditable=CheckPermissions();
}
private bool CheckPermissions()
{
//Check the conditions and return true or false;
}
So view will be clean like ths
@if (Model.IsEditable)
{
//Markup for editable region
}
回答2:
IMHO, it sounds valid enough.
UPDATE: removed irrelevant commentary, and edited to indicate a primary concern.
Now, taking a closer look, especially with the controller action, I strongly recommend that you eliminate the hidden fields (except the one that you need to re-load the record from your back end).
A savvy user can tamper with the hidden form data (all the form data) and your controller action will happily send it all back to the server.
In reality, you should post back only the fields that are permitted to be changed, rehydrate the record from the back end, and transfer the "editable" fields to the fresh copy. This also comes closer to addressing concurrent edit and stale record issues.
来源:https://stackoverflow.com/questions/10326538/view-or-hide-a-dropdownlist-in-my-razor-view-using-helper-method