I have the following in a view I created, but the model.UserName is not recognized:
#model AcmeMVC.Models.SelectUserRolesViewModel
#{
ViewBag.Title = "User Roles";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Roles for user #Html.DisplayFor(model => model.UserName)</h2>
If I add: #using AcmeMVC.Models it will work.
But, I have this entry in the web.config in my Views folder:
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
.....
<add namespace="AcmeMVC" />
<add namespace="AcmeMVC.Models" />
.....
I thought this would make it so I didn't need the using statement, but I still do.
Does anyone have any clue on what I could be doing wrong here?
Modify this line
<h2>Roles for user #Html.DisplayFor(model => model.UserName)</h2>
So it is like this
<h2>Roles for user #Html.DisplayFor(m=>m.UserName)</h2>
The #model is directive to indicate you want to use strongly-typed model classes within your view. It is not a reference to an instance of the object. To access the model in your View you can use an expression (i.e. m=>m.Property)
Related
I have
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
in my config and
Html.EnableClientValidation(true);
Html.EnableUnobtrusiveJavaScript(true);
in my view and
<script src="~/js/jquery.validate.min.js"></script>
<script src="~/js/jquery.validate.unobtrusive.min.js"></script>
are in the HTML source (as is jQuery) (no JS errors in the browser)
I have one form element with [Required] and the form element seems to be rendering OK with the associated data- attributes
<div class='form-group'>
<label class="col-md-2 control-label" for="Username">en-gb(Username)</label>
<div class='col-md-10'>
<div class='input-group'>
<div class='input-group-addon'><span class='fa fa-user'></span></div>
<input class="input-validation-error form-control" id="Username" name="Username" type="text" value="" />
</div>
<span class="field-validation-error help-block" data-valmsg-for="Username" data-valmsg-replace="true">en-gb(The en-gb(Username) field is required.)</span>
</div>
</div>
But no client side validation is occurring; the form is always submitted to the server.
What am I missing? What should I be checking?
Edit
TextBoxFor is in System.Web.Mvc.Html.InputHelpers and calls TextBoxHelper which in turn calls InputHelper in the same file. This calls
htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata) which looks like this:
public IDictionary<string, object> GetUnobtrusiveValidationAttributes(string name, ModelMetadata metadata)
{
Dictionary<string, object> results = new Dictionary<string, object>();
// The ordering of these 3 checks (and the early exits) is for performance reasons.
if (!ViewContext.UnobtrusiveJavaScriptEnabled)
{
return results;
}
FormContext formContext = ViewContext.GetFormContextForClientValidation();
if (formContext == null)
{
return results;
}
string fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
if (formContext.RenderedField(fullName))
{
return results;
}
formContext.RenderedField(fullName, true);
IEnumerable<ModelClientValidationRule> clientRules = ClientValidationRuleFactory(name, metadata);
UnobtrusiveValidationAttributesGenerator.GetValidationAttributes(clientRules, results);
return results;
}
(Source: http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/5cb74eb3b2f3#src/System.Web.Mvc/HtmlHelper.cs)
The problem I have is that formContext.RenderedField(fullName) returns true and therefore no validation attributes are added to my input element.
In your views, are you rendering the following code?
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Assuming you're using the default project template, you'll need to include that within the view that you're rendering to enable client side validation... Alternatively, add Scripts.Render("~/bundles/jqueryval") to the bottom of your layout file to enable it across all your views.
Also do ensure that bundles/jqueryval is defined in the Bundles configuration file.
formContext.RenderedField(fullName) was a red herring, I really don't know what all that was about.
The problem is that I've subclassed the ValidationAttribute classes in order to provide globalisation with lookup from a database rather than from resx. This means that they do not appear in the ModelMetadata.
One solution is to implement the interface System.Web.Mvc.IClientValidatable on the overridden attributes. However, the base classes do not implement this interface, so they must be configuring client side validation by some other mechanism -- and it's this other mechanism that isn't smart enough to pick up subclasses of the out-of-the-box ValidationAttributes.
I have an MVC 5 app, and I'm using data annotations to do a majority of validation. One of the properties in my class looks like this:
[Required(ErrorMessage = "Please enter a business name")]
[StringLength(80)]
public string BusinessName { get; set; }
The validation is working but it doesn't appear to be happening in the browser like I thought it should. On my page I have a Save button. If I leave the Business Name field blank and click Save, a post is done to a controller method that looks, partially, as follows:
[HttpPost]
public ActionResult Create(Advertiser advertiser, FormCollection collection, HttpPostedFileBase file)
{
// Before we do anything, let's check to make sure any validation that's already been done is clean.
if (!ModelState.IsValid)
{
return View(advertiser);
}
...
...
}
When this method is executed, the model state is already set to invalid. That's good because it is invalid because the Business Name field is empty. However, shouldn't this validation be happening in the client?
The field in my .cshtml file looks as follows (using Bootstrap):
<div class="form-group">
#Html.Label("Business Name", new { #class = "control-label col-md-3" })
<div class="col-md-9">
#Html.TextBoxFor(model => model.BusinessName, new { #class = "form-control", title = "", autofocus = true })
#Html.ValidationMessageFor(model => model.BusinessName)
</div>
</div>
My Web.Config is set correctly as follows:
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
I found my problem. In my BundleConfig.cs I have the following:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.min.js",
"~/Scripts/jquery-ui-1.10.4.min.js",
"~/Scripts/jquery.base64.js"
));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.min.js",
"~/Scripts/jquery.validate.unobtrusive.min.js"
));
But, what I didn't realize is that the jqueryval bundle DOES NOT get loaded in the _Layout.cshtml file by default. So I needed to add it, as follows:
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
Once I did this, it is working as it should. Of course, this will cause it to get loaded for all pages. That may not be desirable. If not, load it separately in each page as necessary.
I am inheriting a project which is somewhat built in Umbraco 6 and I am not familiar with Umbraco but learning thus far.
A partial view is using an existing template which effectively has this in its template:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = "MvcBanner.cshtml";
}
#section ContentPlaceHolderParent {
#Umbraco.RenderMacro("Breadcrumb")
#Umbraco.Field("pageName")
#Umbraco.Field("pageInstructions", insertBefore: "", insertAfter: "", convertLineBreaks: true)
#Html.Action(#Umbraco.Field("MVCActionName").ToString(), #Umbraco.Field("MVControllerName").ToString())
}
This template is being used by a page "UploadJobs.cshtml"
Now, on the UploadJobs.cshtml I have a few fields bound to a model and then a file upload:
#model Models.JobsModel
#using(Html.BeginUmbracoForm("UploadJobs", "Jobs"))
{
#Html.TextBoxFor(m => m.Name);
#Html.TextBoxFor(m => m.Files, new { type = "file", name = "Files" })
<input type="submit" value="Upload" id="cmdSubmitJobs" />
}
My action method looks like this:
[HttpPost]
[ValidateAntiForgeryToken]
public PartialViewResult UploadJobs(UploadJobs model)
{ ... }
When submitting, everything seems fine but when returning the model back to the view (i.e validation fails), it seems to break the page completely when rendering (i.e all styles and all formatting is gone) and any javascript//jquery functions I have returns errors when the document is being rendered
thoughts? I want to be able to obviously return the model if it is invalid
Ahmed,
your problem is probably because of you are redirecting to the partialview not the view itself. Double check your flow, the partial page is most likely called from another view (parent one). This parent view contains all required styling stuff within it.
I'm trying to post a model back to my controller. I'm not sure why TextBoxFor works and TextBox does not.
#ModelType Models.myModel
#Code
ViewData("Title") = "Foo"
End Code
#Using (Html.BeginForm())
#Html.AntiForgeryToken()
#Html.TextBoxFor(Function(m) m.Value) <--- works
#Html.TextBox(Model.Value) <--- does not work
#Html.TextBox("Value", Model.Value) <--- works! (per answer below)
#<input type="submit" value="Save" />
End Using
Html.TextBoxFor creates right input type="text" with correct name value. You mustn't use it, but it helps in this case. Same result may be achieved even with html code:
<input type="text" name="Value" value="#Model.Value" />
Main point for asp.net mvc model binders is correct names for html controls. Html.TextBox() also does it, using first parameter as html element name, so correct usage of it should be Html.TextBox("Value", Model.Value)
Im kinda new in MVC4 and im not able to figure it out.
"CustomViewMOdel" "CustomViewMOdel"
"ControllerX" ----------------> "VIEW" -----------------> "ControllerY"
My problem is that i want to pass my customviewmodel to view (which is working just fine!). In the View im showing some of model's fields to users (which is working fine also). BUT Now i want user, to change ONE field of the models fields and then PASS the WHOLE model to Controller X (with all fields filled, including the field what user was able to change AND other fields what were just shown)
Can anyone give a very simple code example of how to do this?
You can just create a form that posts to another controller:
ControllerX:
public ActionResult DoSomething()
{
return View(new CustomVM());
}
ViewA
#Model CustomViewModel
#using Html.BeginForm("DoSomethingElse", "ControllerY")
{
#Html.EditorFor(vm => vm.SomeProperty)
<input type="submit" value="OK" />
}
ControllerY
public ActionResult DoSomethingElse(CustomViewModel vm)
{
// do something else
}
You can use #Html.HiddenFor(o => o.Property) on the form.
This will not show a property on it.
But the advanced user may change the property through a development console. So you should check all the changes in the ControllerY
Example:
#Html.HiddenFor(o => o.Id)
#Html.HiddenFor(o => o.Name)
#Html.EditorFor(o => o.Description)
<input type="submit" value="OK" />
This will only let the user change a description but still have "id" and "name" on the FormCollection.