my application is MVC3 ASPX C#; I am trying to enable/disable Html.EditorFor using the following:
In the Model:
public bool IsReadOnly { get; private set; }
In the controller:
if (MySession.Current._progress == 100)
ViewData["ReadOnly"] = true;
In the view:
... Inherits="System.Web.Mvc.ViewPage<Models.CTAHFormEdit>" %>
<script runat="server" type="text/C#">
bool isReadOnly = false;
protected void Page_Load(object sender, EventArgs e)
{
if ((bool?)this.ViewData["ReadOnly"] == true)this.isReadOnly = true;
}
</script>
<%: Html.EditorFor(model => model.Vessel_calcification, Model.IsReadOnly)%>
This did not work. I also tried:
<%: Html.EditorFor(model => model.Subject_motion, new { #disable = true })%>
did not work also!
The best solution, becasue I also have dropdownlist and checkbox in the same view is to use #disable = true and #readonly = true or false and be able to change true of false using a ViewBag. Any suggestions, thanks in adavance.
You can try this:
#Html.TextBoxFor(model => model.Subject_motion, new { #readonly = "readonly" })
Here's an explanation of the difference between EditorFor and TextBoxFor:
Differences between Html.TextboxFor and Html.EditorFor in MVC and Razor
Related
I have a form where either at least one checkbox must be checked OR a textbox is filled in.
I have a ViewModel that populates the CheckboxList and takes the selected values plus the textbox (other) value when required to a SelectedWasteTypes property within the ViewModel. I think my problem is I can't validate against this property as there is no form element on the view that directly relates to it. I've very new to MVC and this one has stumped me.
From the ViewModel
public List<tblWasteTypeWeb> WasteTypeWebs { get; set; }
public string WasteTypeWebOther { get; set; }
public string SelectedWasteTypes { get; set; }
View (segment)
#using (Html.BeginForm("OrderComplete", "Home"))
{
//Lots of other form elements
#for (var i = 0; i < Model.WasteTypeWebs.Count; i++)
{
var wt = Model.WasteTypeWebs[i];
#Html.LabelFor(x => x.WasteTypeWebs[i].WasteTypeWeb, wt.WasteTypeWeb)
#Html.HiddenFor(x => x.WasteTypeWebs[i].WasteTypeWebId)
#Html.HiddenFor(x => x.WasteTypeWebs[i].WasteTypeWeb)
#Html.CheckBoxFor(x => x.WasteTypeWebs[i].WasteTypeWebCb)
}
<br />
<span>
#Html.Label("Other")
#Html.TextBoxFor(x => x.WasteTypeWebOther, new { #class = "form-control input-sm" })
</span>
//More form elements
<input type="submit" value="submit" />
}
Controller Logic (if you can call it that)
[HttpPost]
public ActionResult OrderComplete(OrderViewModel model)
{
var sb = new StringBuilder();
if (model.WasteTypeWebs.Count(x => x.WasteTypeWebCb) != 0)
{
foreach (var cb in model.WasteTypeWebs)
{
if (cb.WasteTypeWebCb)
{
sb.Append(cb.WasteTypeWeb + ", ");
}
}
sb.Remove(sb.ToString().LastIndexOf(",", StringComparison.Ordinal), 1);
}
model.SelectedWasteTypes = sb.ToString();
if (!string.IsNullOrEmpty(model.WasteTypeWebOther))
{
if (!string.IsNullOrEmpty(model.SelectedWasteTypes))
{
model.SelectedWasteTypes = model.SelectedWasteTypes.TrimEnd() + ", " + model.WasteTypeWebOther;
}
else
{
model.SelectedWasteTypes = model.WasteTypeWebOther;
}
}
return View(model);
}
I very much feel I'm up a certain creek... I've thought about using JQuery, but ideally I'd like server side validation to be sure this info is captured (its a legal requirement). However, if this can only be achieved client side, I will live with it.
Any suggestions?
Take a look at the MVC Foolproof Validation Library. It has validation attributes for what you are trying to accomplish: [RequiredIfEmpty] and [RequiredIfNotEmpty]. You can also take a look at my previous SO answer about Conditional Validation.
I would suggest you to implement IValidatableObject in your ViewModel.
Inside Validate( ValidationContext validationContext) method you can check weather your conditions are met. For example:
if(string.IsNullOrWhiteSpace(WasteTypeWebOther))
yield return new ValidationResult("Your validation error here.");
When my page loads in "edit" mode, my text fields render correctly, but my numeric fields render with the error validation text visible, even though the value in the field is valid:
My problem is in a more complex project, but I was able to reproduce it in an out-of-the-box MVC 3 application in which I just added these bits. Why does the numeric field display the error text but the text field is fine when the page loads?
What is going on here?
I have the following for my Model, Controller, and View:
Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace MvcIssues.Models
{
public enum Operations
{
View = 0,
Edit = 1
}
public class ShowsModel
{
public Operations Operation { get; set; }
[Display(Name = "Name")]
[DataType(DataType.Text)]
[StringLength(10)]
public string Name { get; set; }
[Display(Name = "Number")]
[Required]
[Range(typeof(int), "1", "999")]
public int Number { get; set; }
}
}
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcIssues.Models;
using MvcIssues.Data;
namespace MvcIssues.Controllers
{
public class TestController : Controller
{
// GET: /Test/Shows
[AcceptVerbs(HttpVerbs.Get)]
[ActionName("Shows")]
[Authorize]
public ActionResult SelectedShows()
{
ShowsData shows = MvcApplication.Shows;
ShowsModel model = new ShowsModel();
model.Operation = Operations.View;
model.Name = shows.Name;
model.Number = shows.Number;
return View(model);
}
// POST: /Test/Shows
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Shows")]
[ValidateInput(false)]
[Authorize]
public ActionResult ShowsSubmit(ShowsModel data)
{
string name = data.Name;
int number = data.Number;
ShowsModel model = new ShowsModel();
if (Request.Form.AllKeys.Contains("btnEdit"))
{
ShowsData shows = MvcApplication.Shows;
model.Name = shows.Name;
model.Number = shows.Number;
model.Operation = Operations.Edit;
}
else if (Request.Form.AllKeys.Contains("btnCancel"))
{
ShowsData shows = MvcApplication.Shows;
model.Name = shows.Name;
model.Number = shows.Number;
model.Operation = Operations.View;
}
else if (Request.Form.AllKeys.Contains("btnSaveEdit"))
{
ShowsData shows = MvcApplication.Shows;
shows.Name = name;
shows.Number = number;
model.Name = shows.Name;
model.Number = shows.Number;
model.Operation = Operations.View;
}
return View("Shows", model);
}
}
}
View:
#model MvcIssues.Models.ShowsModel
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<h2>Test Page</h2>
<div>
Show = #this.ViewData.Model.Name
<br />
Number = #this.ViewData.Model.Number.ToString()
</div>
<hr />
<div>
#Html.ValidationSummary(true, "oops!")
#using (Html.BeginForm())
{
<div>
Name: #(this.ViewData.Model.Operation == MvcIssues.Models.Operations.View ?
Html.TextBoxFor(m => m.Name, new { disabled = "disabled", maxLength = "20" })
:
Html.TextBoxFor(m => m.Name))
#Html.ValidationMessageFor(m => m.Name)
<br />
Number: #(this.ViewData.Model.Operation == MvcIssues.Models.Operations.View ?
Html.TextBoxFor(m => m.Number, new { disabled = "disabled" })
:
Html.TextBoxFor(m => m.Number))
#Html.ValidationMessageFor(m => m.Number)
</div>
<div>
#switch (this.ViewData.Model.Operation)
{
case MvcIssues.Models.Operations.Edit:
<input type="submit" name="btnSaveEdit" value="Save" />
<input type="submit" name="btnCancel" value="Cancel" />
break;
case MvcIssues.Models.Operations.View:
default:
<input type="submit" name="btnEdit" value="Edit" />
break;
}
</div>
}
</div>
If anyone can help me it would be much appreciated.
I had the same problem too. Here's what caused it, and how I fixed it:
The cause:
[Authorize]
[HttpGet]
public ActionResult BidToolv2(BidToolv2ViewModel model)
{
...
The fix:
[Authorize]
[HttpGet]
public ActionResult BidToolv2()
{
BidToolv2ViewModel model = new BidToolv2ViewModel();
Essentially the problem was when the user first visited the page, the controller took an empty model and when the page loaded, it assumed it had already been passed the model (perhaps?). Not totally sure on that, but to fix it I removed the model as a parameter and instead created a model in the controller action itself
Hope this helps!
Okay, posted this to asp.net forum. Probably a little bit more concisely worded version of the same question.
Solution was a bit of a hack but seems to be working well - created empty constructors for my problematic view model classes and inside the empty constructors I initialized the properties to valid values. Did the trick.
You need Required to make sure something is entered.
You need Range to make sure when something is entered that the values meet your requirements
Example:
[Required(ErrorMessage="Weekly Rental value is required")]
[Range(1, 9999, ErrorMessage = "Value must be between 1 - 9,999")]
public string WeeklyRental { get; set; }
I have a View that handles the Edit action for editing a weekly update on your weight and nutrition. Editing a singular model is all good. I am using EditorFor to create the fields.
My problem is that I want to also display a read only version of last week's results as a guide but I would like to use DisplayFor so that it formats bools to be disabled checkboxes and formats the dates based on my formatting in the model. I added the model to the Viewbag and tried to access it by using #Html.DisplayFor(x => x.BodyWeight, (myproject.Models.WeeklyReport)ViewBag.LastReport) however it just brings up the data in the model that I sent to the view and not the Viewbag data. What is the best method to display this kind of data while keeping the constraints/formatting of the model intact?
Thanks.
View
#model myproject.Models.WeeklyReport
<h2>Weekly Report - Week 1</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<table class="weeklyreport">
<tr>
<th>Week</th>
<td class="result-bold">Goals</td>
<td>Current Week</td>
</tr>
<tr>
<th>Body Weight</th>
<td class="result-bold">#Html.DisplayFor(x => x.BodyWeight, (myproject.Models.WeeklyReport)ViewBag.Goals)</td>
<td>#Html.EditorFor(model => model.BodyWeight)
#Html.ValidationMessageFor(model => model.BodyWeight)</td>
</tr>
<tr>
<th>Diary Reviewed</th>
<td class="result-bold">#Html.DisplayFor(x => x.DiaryReviewed, (myproject.Models.WeeklyReport)ViewBag.Goals)</td>
<td>#Html.EditorFor(model => model.DiaryReviewed)
#Html.ValidationMessageFor(model => model.DiaryReviewed)</td>
</tr>
</table>
Controller
public ActionResult Edit(int id)
{
WeeklyReport goal = new WeeklyReport()
{
BodyWeight = 60,
DiaryReviewed = true
};
WeeklyReport rpt = new WeeklyReport()
{
BodyWeight = 68,
DiaryReviewed = false
};
ViewBag.LastReport = goal;
return View(rpt);
}
You can create a viewmodels or partialViews and pass the viewbag item to the partial.
An example of viewmodel usage
public class WeeklyReportViewModel
{
public WeeklyReport LastReport { get; set; }
public WeeklyReport Report { get; set; }
}
combine the reports
public ActionResult Edit(int id)
{
WeeklyReport goal = new WeeklyReport()
{
BodyWeight = 60,
DiaryReviewed = true
};
WeeklyReport rpt = new WeeklyReport()
{
BodyWeight = 68,
DiaryReviewed = false
};
WeeklyReportViewModel viewmodel = new WeeklyReportViewModel()
{
LastReport = goal,
ActualReport = rpt
}
return View(viewmodel);
}
In the view
#model myproject.ViewModels.WeeklyReportViewModel
#Html.DisplayFor(x => x.LastReport.BodyWeight)
this is my Model1 class
namespace chetan.Models
{
public class Model1
{
public string selectedItem { get; set; }
public IEnumerable<SelectListItem> items { get; set; }
}
}
this is my controller class
public class HomeController : Controller
{
private rikuEntities rk = new rikuEntities();
public ActionResult Index()
{
var model = new Model1
{
items = new[]
{
new SelectListItem { Value = "Theory", Text = "Theory" },
new SelectListItem { Value = "Appliance", Text = "Appliance" },
new SelectListItem { Value = "Lab", Text = "Lab" }
}
}; return View(model);
}
public ActionResult viewToController(Model1 m)
{
string getSelectedName = m.selectedItem;
return Content(getSelectedName);
}
}
this is my view...
#using (Html.BeginForm("viewToController", "Home"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>emp</legend>
<div class="editor-field">
#Html.DropDownListFor(x => x.selectedItem,
new SelectList(Model.items, "Value", "Text"))
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
i want to add a drop downlist and i want to use selected value in viewToController action of homeController. and there is also one error in View page is "an expression tree may not contain dynamic operation" in (x=>x.selectedItem). Please solve my problem .
I don't understnad what you exactly need. You want to dynamicly add items to the drop down from the database?
I'm big fan of jQuery. You can do everything what you want with HTML using jQuery. So if you are looking how to automaticly add items to the drop down, take look at this: How do I add options to a DropDownList using jQuery?
I need to check a checkbox by default:
I tried all of these, nothing is checking my checkbox -
#Html.CheckBoxFor(m => m.AllowRating, new { #value = "true" })
#Html.CheckBoxFor(m => m.AllowRating, new { #checked = "true" })
#Html.CheckBoxFor(m => m.AllowRating, new { #checked = true })
#Html.CheckBoxFor(m => m.AllowRating, new { #checked = "checked"})
You should set the AllowRating property to true, preferably in the controller or model.
Like other inputs, the checkbox's state reflects the value of the property.
This works for me:
<input id="AllowRating" type="checkbox" #(Model.AllowRating?"checked='checked'":"") style="" onchange="" />
If you really wants to use HTML Helpers:
#Html.CheckBoxFor(m => m.AllowRating, new { #checked = Model.AllowRating})
Also take into account that if m.AllowRating is false, it will fail to set to status checked in your examples.
The syntax in your last line is correct.
#Html.CheckBoxFor(x => x.Test, new { #checked = "checked" })
That should definitely work. It is the correct syntax. If you have an existing model and AllowRating is set to true then MVC will add the checked attribute automatically. If AllowRating is set to false MVC won't add the attribute however if desired you can using the above syntax.
You can do this with #Html.CheckBoxFor():
#Html.CheckBoxFor(m => m.AllowRating, new{#checked=true });
or you can also do this with a simple #Html.CheckBox():
#Html.CheckBox("AllowRating", true) ;
you set AllowRating property to true from your controller or model
#Html.CheckBoxFor(m => m.AllowRating, new { #checked =Model.AllowRating })
<input type="checkbox" #( Model.Checked == true ? "checked" : "" ) />
only option is to set the value in the controller, If your view is Create then in the
controller action add the empty model, and set the value like,
Public ActionResult Create()
{
UserRating ur = new UserRating();
ur.AllowRating = true;
return View(ur);
}
If we set "true" in model, It'll always true. But we want to set option value for my checkbox we can use this. Important in here is The name of checkbox "AllowRating", It's must name of var in model if not when we post the value not pass in Database.
form of it:
#Html.CheckBox("NameOfVarInModel", true) ;
for you!
#Html.CheckBox("AllowRating", true) ;
I had the same issue, luckily I found the below code
#Html.CheckBoxFor(model => model.As, htmlAttributes: new { #checked = true} )
Check Box Checked By Default - Razor Solution
I did it using Razor , works for me
Razor Code
#Html.CheckBox("CashOnDelivery", CashOnDelivery) (This is a bit or bool value) Razor don't support nullable bool
#Html.CheckBox("OnlinePayment", OnlinePayment)
C# Code
var CashOnDelivery = Convert.ToBoolean(Collection["CashOnDelivery"].Contains("true")?true:false);
var OnlinePayment = Convert.ToBoolean(Collection["OnlinePayment"].Contains("true") ? true : false);