I am trying to use the following helper class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Web.Mvc;
using System.Web.Routing;
namespace myNamespace
{
public static class ValidationHelper
{
public static MvcHtmlString ValidationImage(this HtmlHelper helper, string name)
{
if (helper.ViewData.ModelState[name] == null || helper.ViewData.ModelState[name].Errors == null || helper.ViewData.ModelState[name].Errors.Count == 0)
{
return MvcHtmlString.Empty;
}
var tag = new TagBuilder("img");
tag.Attributes.Add("src", "../Content/Images/check_bg_invalid.png");
tag.Attributes.Add("alt", helper.ViewData.ModelState[name].Errors[0].ErrorMessage);
tag.Attributes.Add("title", helper.ViewData.ModelState[name].Errors[0].ErrorMessage);
tag.Attributes.Add("class", HtmlHelper.ValidationMessageCssClassName);
return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing));
}
}
}
And using this in a view:
#Html.ValidationImage("FirstName")
to try and get an image to fire when there is a validation error.
So I have my:
#Html.TextBox("FirstName", null, new { #class = "my_input" })
in the same view (all within the #Html.BeginForm)
This is my model.cs class:
public class QuoteModel
{
[Required(ErrorMessage = "You must specify a First Name.")]
public string First Name { get; set; }
}
And this is my controller.cs class:
public ActionResult Quote()
{
//return View();
var model = new QuoteModel();
return View(model);
}
[HttpPost]
public ActionResult Quote(QuoteModel model)
{
if (ModelState.IsValid)
{
try
{
}
catch (Exception)
{
return View(model);
}
}
return RedirectToAction("QuoteSuccess");
}
public ViewResult QuoteSuccess()
{
return View();
}
Bear in mind, I may have made a typo in all of the preceding code blocks.
Originally, I used
#Html.ValidationMessage("FirstName")
and the Error Message would fire after clicking send. I am trying to now use the above helper for ValidationImage, but nothing fires (and the Error Message doesn't show). Nor is anything output with an <img> tag. No errors are thrown on the page.
As an aside, I have two other questions:
1) I would also like to display a validation success message (i.e., a little image with "OK"), but am having trouble just getting above to work in the first instance.
2) I was previously unsuccessful (before using helper) to get client side validation to show.
Am using
#{ Html.EnableClientValidation(); }
in that same view. I placed it at the top (after #model). Does placement matter?
I also used the following in my _layout.cshtml
<script language="javascript" src="#Url.Javascript("jquery.validate.min")" type="text/javascript"></script>
<script language="javascript" src="#Url.Javascript("jquery.validate.unobtrusive.min")" type="text/javascript"></script>
Note that I use a helper, so no need for ".js" extension - this has worked in the past and shows up in view source. So no problems there.
Finally, I do have my web.config set up thusly:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Any thoughts on either of my problems (particularly the main one) are much appreciated.
It looks to me like your validation image will only be output in the page if the server-side validation fails. This means your client-side validation can't possibly show the image, as it won't exist in the HTML markup (return MvcHtmlString.Empty;)
If you want the validation to work client-side (and show the image), you might have to do some work to hook into the existing validation. There's an article here about custom validation:
http://www.codeproject.com/Articles/98376/Including-custom-client-side-validations-in-your-A.aspx
Though it might be a little overly complicated - there may be an easier way to hook into it (though I can't find one just now).
Related
I'm using editor from Kendo UI, so I have big problem.
I don't know how display items which are returned by editor.
Editor convert something like:
<img src="someurl" />
to:
lt;p><img src="someurl"/></p>
and I keep converted string in database, and try display it with:
#Html.Raw(item.description)
where description is string returned by kendo.
So I have no idea how display it correctly in my View
Any help would be appreciated.
There is an option of the KendeUI editor called encoded which configures whether the Editor should submit encoded HTML tags or not.
The default value for encoded is true
If you wan't to store the unencoded text use this sniplet when creating your editor:
$("#Editor").kendoEditor({
encoded: false
});
But because you are not sending encoded text to the server the Asp.net request validator kicks in and it will abort your request.
If you are using strongly typed views what you can do is to use the AllowHtmlAttribute on your model property:
View:
#model MyModel
#using(Html.BeginForm("SomeAction", "SomeController"))
{
#Html.TextAreaFor(m => m.Editor)
<input type="submit" value="Save" />
}
<script type="text/javascript">
$(function(){
$("#Editor").kendoEditor({
encoded: false
});
});
</script>
Model:
public class MyModel
{
[AllowHtml]
public string Editor { get; set; }
}
Controller action
public ActionResult SomeAction(MyModel myModel)
{
//Save to db, etc.
}
You also need to set the following in your web.config or this attribute won't have effect in .NET 4.0:
<httpRuntime requestValidationMode="2.0"/>
I found this solution for MVC:
in View
<div class="editor-field">
#(Html.Kendo().EditorFor(model => model.HtmlField).Encode(false))
#Html.ValidationMessageFor(model => model.HtmlField)
</div>
in model:
[DataType(DataType.Html)]
[AllowHtml]
public string HtmlField{ get; set; }
That was enough
Simplier way to do it is make changes in controller, no in view and model. So:
View
$("#Editor").kendoEditor();
Model
public class MyModel
{
public string Editor { get; set; }
}
Controller
Editor = Server.HtmlDecode(Editor);
HtmlDecode
The editor templates generated from the .NET Wrappers aren't working any more. Here is a fix.
http://pknopf.com/blog/kendo-ui-editor-templates-for-asp-net
In an MVC3 project, i use an Html.BeginForm to post some (model-)values. Along with those i want to send an extra parameter that is not part of the form (the model) but in the ViewBag. Now, when i use a Button (code in answer here: MVC3 razor Error in creating HtmlButtonExtension), all the form values are posted but the extra parameter remains null. When i use an ActionLink, the parameter is posted but the form values are not :) Any know how i can combine the two? Thanks!
#Html.Button("Generate!", new { id = ViewBag.ProjectID })
#Html.ActionLink("Generate!", "Post", new { id = #ViewBag.ProjectID })
My advice would be to declare a new Object in your App.Domain.Model something like this
namespace App.Domain.Model
{
public class CustomEntity
{
public Project projectEntity { get; set; }
public int variableUsed { get; set; }
}
}
In your view you can acces them easily by using CustomEntity.projectEntity and CustomEntity.variableUsed.
Hope it helps
You can do something like below.
View code
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new { #id = "frmId", #name = "frmId" }))
{
#*You have to define input as a type button not as a sumit. you also need to define hidden variable for the extra value.*#
<input type="hidden" name="hndExtraParameter" id="hndExtraParameter" />
<input value="Submit" type="button" id="btnSubmit" onclick="UpdateHiddenValue()" />
}
<script type="text/javascript">
function ValidateUser() {
$("#hndExtraParameter").val('Assignvaluehere');
$("#frmId").submit();
}
</script>
Controller Code
[HttpPost]
public ActionResult ActionName(Model model, string hndExtraParameter)
{
//Do your operation here.
}
I have the following view model
public class FooViewModel
{
public int SelectedCategoryId { get; set; }
public IEnumerable<CategoryDto> AvailableCategories { get; set; }
}
in my view I am using jquery template to bind my data to a select tag
<script type="text/javascript">
$(document).ready(function () {
var categories = #Model.AvailableCategories.ToJson();
var categoryMarkup = '<option value="${Id}"${Selected}>${Name}</option>';
$.template("categoryTemplate", categoryMarkup);
$.tmpl("categoryTemplate", categories).appendTo($('#categories'));
});
</script>
<select id="categories"></select>
What would I need to do to make sure my SelectedCategoryId viewmodel property gets populated on the POST? I'd prefer not to use the Html.DropDownList if I can get away with it
Simply add it in your form using the html helpers. Ex.
Html.HiddenFor(o=>o.SelectCategoryId)
If your combo box is changing this then simply set an onchange event
("#selectId").change(function(){
//something like this - untested
$("#SelectCategoryId").val(this.value);
});
Unless you are using an explicit jQuery .ajax() call in that case you will need to add this value to the data. Which are you using when you post? I don't see your form above anywhere
I'm attempting to add a classic Accept Terms and Conditions checkbox on the log on page of an MVC application.
If the user accepts the Terms and Conditions, but fails to log on for some other reason (bad password etc), then I want the Accept T&Cs checkbox not to be checked, so the user is forced to accept the T&Cs on every log on attempt.
The problem is that using Html.CheckboxFor(), after a postback the checkbox retains its previous value, despite the value of the bound Model property.
Here's the code, stripped down to essentials. If you run this code up, check the checkbox, and click the button, you'll be returned to the form with the checkbox still checked, even though the bound model property is false.
The Model:
namespace Namespace.Web.ViewModels.Account
{
public class LogOnInputViewModel
{
[IsTrue("You must agree to the Terms and Conditions.")]
public bool AcceptTermsAndConditions { get; set; }
}
}
The validation attribute:
public class IsTrueAttribute : ValidationAttribute
{
public IsTrueAttribute(string errorMessage) : base(errorMessage)
{
}
public override bool IsValid(object value)
{
if (value == null) return false;
if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
return (bool)value;
}
}
The View:
#model Namespace.Web.ViewModels.Account.LogOnInputViewModel
#using (Html.BeginForm()) {
#Html.CheckBoxFor(x => x.AcceptTermsAndConditions)
<input type="submit" value="Log On" />
}
The Controller:
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
[HttpPost]
public ActionResult LogOn(LogOnInputViewModel input)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
I saw the suggestion on asp.net to add a #checked attribute to the CheckboxFor. I tried this, making the view
#model Namespace.Web.ViewModels.Account.LogOnInputViewModel
#using (Html.BeginForm()) {
#Html.CheckBoxFor(x => x.AcceptTermsAndConditions, new { #checked = Model.AcceptTermsAndConditions })
<input type="submit" value="Log On" />
}
And I saw the same behaviour.
Thanks for any help/insights!
Edit: Although I want to override the posted back value, I wish to retain the message if validation of AcceptTermsAndConditions fails (there is a validation attribute on AcceptTermsAndConditions requiring it to be true), so I can't use ModelState.Remove("AcceptTermsAndConditions") which was the otherwise sound answer #counsellorben gave me. I've edited the code above to include the validation attribute - apologies to #counsellorben for not being clearer originally.
You need to clear the ModelState for AcceptTermsAndConditions. By design, CheckBoxFor and other data-bound helpers are bound first against the ModelState, and then against the model if there is no ModelState for the element. Add the following to your POST action:
ModelState.Remove("AcceptTermsAndConditions");
One again Microsoft poor documentation has left me confused. I am trying to use the new features of the .NET 4.0 framework. I am using the following code to populate the Title and Director but it keeps getting blank.
The service returns the result correctly like
[d: { title = "ss, director ="" } something like that but the li never gets populated.
<script language="javascript" type="text/javascript">
Sys.require([Sys.components.dataView, Sys.components.dataContext,Sys.scripts.WebServices], function () {
Sys.create.dataView("#moviesView",
{
dataProvider: "MovieService.svc",
fetchOperation: "GetMovies",
autoFetch: true
});
});
</script>
And here it the HTML code:
<ul id="moviesView">
<li>
{{Title}} - {{Director}}
</li>
</ul>
IS THIS THE LATEST URL TO Start.js file.
<script src="http://ajax.microsoft.com/ajax/beta/0911/Start.js"></script>
Here is the Ajax-Enabled WCF Service:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MovieService
{
[OperationContract]
public Movie GetMovies()
{
return new Movie() { Title = "SS", Director = "SSSSS" };
}
}
[DataContract]
public class Movie
{
[DataMember]
public string Title { get; set; }
[DataMember]
public string Director { get; set; }
}
You need to add the sys-template class attribute to the unordered list tag.
<ul id="moviesView" class="sys-template">
Here's an excerpt from Client-side Data Binding in ASP.NET AJAX 4.0
The one other requirement for defining
a template is the parent element must
have the sys-template CSS class
applied, and that class must be
defined with display set to none, as
shown in the example above. This
convention serves two purposes – it
helps the parser identify which
elements are part of a template on
your page (which will become important
when we use declarative
instantiation), and it keeps the
template markup hidden until ASP.NET
Ajax has completed the binding (it
will toggle the display to be
visible).