In my Mvc project I have this model:
namespace CameraWebApp.Models
public class Images
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ImageId { get; set; }
[Required(ErrorMessage="Please enter your first name")]
public string SubmitterFirstName { get; set; }
[Required(ErrorMessage = "Please enter your surname name")]
public string SubmitterLastName { get; set; }
[ExistingFileName]
public string NameOfImage { get; set; }
[StringLength(140, ErrorMessage="Please reduce the length of your description to below 140 characters")]
[DataType(DataType.MultilineText)]
public string DescriptionOfImage { get; set; }
public string ImagePath { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime DateAdded { get; set; }
}
As you can see the NameOfImage property has the attribute [ExistingFileName] which is a custom validator, the code for this validator is below:
//Overiding isValid to make a custom Validator
protected override System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext)
{
if (value!=null)
{
string fileName = value.ToString();
if (FileExists(fileName))
{
//If the file exists use default error message or the one passed in if there is one
return new ValidationResult(ExistingImageErrorMessage ?? defaultExistingImage);
}
else
{
return ValidationResult.Success;
}
}
else
{
//If theres no value passed in then use error message or default if none is passed
return new ValidationResult(ErrorMessage ?? DefaultErrorMessage);
}
}
bool FileExists(string fileName)
{
bool exists = false;
//A list is passed all the images
List<Images> images = cameraRepo.getAllImages().ToList();
//Loops through every image checking if the name already exists
foreach (var image in images)
{
if (image.NameOfImage==fileName)
{
exists = true;
break;
}
}
return exists;
}
Each of the previous properties are being validated Client Side in the code below:
#using (Html.BeginForm())
{
<div id="errorMessages">
#Html.ValidationSummary(false)
</div>
<label>base64 image:</label>
<input id="imageToForm" type="text" name="imgEncoded"/>
<label>First Name</label>
#Html.EditorFor(model => model.SubmitterFirstName)
<label>Last Name</label>
#Html.EditorFor(model => model.SubmitterLastName)
<label>Name of Image</label>
#Html.EditorFor(model => model.NameOfImage)
<label>Image Description</label>
#Html.EditorFor(model => model.DescriptionOfImage)
<input type=button id="button"value=" Camera button"/>
<input type="submit" value="Click this when your happy with your photo"/>
}
</div>
#Html.ActionLink("gfd!!", "DisplayLatest")
<script src="#Url.Content("~/Scripts/LiveVideoCapture.js")" type="text/javascript"></script>
All validation works Client side except my Custom validation [ExisitingFileName] and I have no idea why? Does anyone know why this might be?
Thanks in advance!
Since it is a custom validation, c# mvc cannot generate a client-side validation: you'll have to implement your own custom client-side validation for this field (using Javascript). In it you may want to use AJAX to call a server method to check if filename already exists.
You can also try to use remote validation, which seems to be simpler:
http://msdn.microsoft.com/en-us/library/ff398048(VS.100).aspx
When validating on the client side, you need to implement IClientValidateable. This requires you to write client side validation code (javascript) and server side validation code (C#)
http://forums.asp.net/t/1850838.aspx/1
This post is also helpful
http://odetocode.com/Blogs/scott/archive/2011/02/22/custom-data-annotation-validator-part-ii-client-code.aspx
Related
I am attempting to write a generic framework to assist with developing wizard-style forms.
I have a model with properties representing each step in the wizard, e.g.
public class ExampleWizardTransaction : WizardTransaction
{
public override TransactionType TransactionType { get; set; } = TransactionType.ExampleWizard;
public override string ControllerName { get; set; } = "WizardExample";
[DisplayName("Client Details")]
public ClientDetails ClientDetails { get; set; } = new ClientDetails();
[DisplayName("Client Questions")]
public ClientQuestions ClientQuestions { get; set; } = new ClientQuestions();
[DisplayName("Client Preferences")]
public ClientPreferences ClientPreferences { get; set; } = new ClientPreferences();
}
[Step(1)]
public class ClientDetails : IStep
{
[Display(Description = "Please enter your first name")]
public string FirstName { get; set; }
[Display(Description = "Please enter your last name")]
public string LastName { get; set; }
}
[Step(2)]
public class ClientQuestions : IStep
{
[DisplayName("What is your favourite car?")]
public string FavouriteCar { get; set; }
[DisplayName("What is your favourite holiday destination?")]
public string FavouriteDestination { get; set; }
}
[Step(3)]
public class ClientPreferences : IStep
{
[DisplayName("Red or Blue?")]
public Colours Colour { get; set; }
[DisplayName("Do you like Indian food")]
public bool LikeFood { get; set; }
}
Initially, I had a partial view for each wizard step which looked like this:
#model Web.Models.ExampleWizard.Create
<div class="row">
<div class="col-md-6">
#Html.EditorFor(x => x.ExampleWizardTransaction.ClientDetails)
</div>
</div>
Using this, the values of my form bind up correctly since when I post it up MVC knows the binding context.
On my form, I render the partial view by passing in the step number, e.g.
Html.RenderPartial($"_CreateWizard_{Model.ExampleWizardTransaction.CurrentStep}", Model);
I'm attempting to generalise the code, so that I don't need to include a partial view for every step in the wizard.
To do that, I'm rendering an action which determines which type is associated with the wizard step and I return a partial view:
Html.RenderAction("GetStep", "ExampleWizard", Model.ExampleWizardTransaction);
My partial view specifies an interface that each wizard step implements:
_WizardStep.cshtml
#model Services.ViewModels.Wizard.IStep
<div class="row">
<div class="col-md-6">
#Html.EditorFor(x => x)
</div>
</div>
When I use the above, the form renders correctly, but the values no longer bind up on the POST, which I assume is because it doesn't have the binding context for the properties (e.g. the id and name of the input types aren't fully qualified).
I have an EditorFor template for the string properties on my wizard steps which renders a textbox:
#model string
<div class="col-md-12">
<div class="form-group">
<label class="m-b-none" for="#ViewData.Model">
#ViewData.ModelMetadata.DisplayName
</label>
<span class="help-block m-b-none small m-t-none">#ViewData.ModelMetadata.Description</span>
<div class="input-group">
#Html.TextBox("", Model, new {#class = "form-control"})
<div class="input-group-addon">
<i class="fa validation"></i>
</div>
</div>
</div>
</div>
Is it possible to use my generic "_WizardStep.cshtml" partial view and still bind up the properties for the current step to my model?
My controller looks like this:
[HttpPost]
public virtual ActionResult CreateWizard(Create model, string action)
{
var createModel = CreateModel<Create>();
switch (createModel.Save(action))
{
case WizardState.Finished:
return RedirectToActionWithMessage("List", "Transaction", "Completed", ToastNotificationStatus.Success);
case WizardState.Ongoing:
return RedirectToAction(MVC.ExampleWizard.CreateWizard(
model.ExampleWizardTransaction.Id,
model.ExampleWizardTransaction.GetNextStep(action)));
default:
model.MapExistingTransactions<ExampleWizardTransaction>();
return View(model);
}
}
My 'Create' model contains my 'ExampleWizardTransaction' property which contains each of the wizard steps which implement the IStep interface.
Taking inspiration from #StephenMuecke's answer, I took the following approach.
On my 'CreateWizard.cshtml' view, I render the step with the following line:
#Html.WizardPartialFor(x => x.ExampleWizardTransaction.GetStepObject<IStep>(), "_WizardStep", Model.ExampleWizardTransaction)
This calls the 'WizardPartialFor' extension method:
public static MvcHtmlString WizardPartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression, string partialViewName, IWizardTransaction wizardTransaction)
{
var compiled = expression.Compile();
var result = compiled.Invoke(helper.ViewData.Model);
PropertyInfo currentStep = wizardTransaction.GetCurrentStepPropertyInfo();
string currentStepName = currentStep.PropertyType.Name;
var name = $"{currentStep.DeclaringType.Name}.{currentStepName}";
var viewData = new ViewDataDictionary(helper.ViewData)
{
TemplateInfo = new TemplateInfo { HtmlFieldPrefix = name }
};
return helper.Partial(partialViewName, result, viewData);
}
public static PropertyInfo GetCurrentStepPropertyInfo(this IWizardTransaction wizardTransaction)
{
var properties = wizardTransaction.GetType().GetProperties()
.Where(x => x.PropertyType.GetCustomAttributes(typeof(StepAttribute), true).Any());
return properties.FirstOrDefault(x => ((StepAttribute)Attribute
.GetCustomAttribute(x.PropertyType, typeof(StepAttribute))).Step == wizardTransaction.CurrentStep);
}
Into this extension method, we call an extension method which gets the wizard step object:
public static TProperty GetStepObject<TProperty>(this IWizardTransaction wizardTransaction)
where TProperty : class
{
var properties = wizardTransaction.GetType().GetProperties()
.Where(x => x.PropertyType.GetCustomAttributes(typeof(StepAttribute), true).Any());
var #object = properties.FirstOrDefault(x => ((StepAttribute)Attribute
.GetCustomAttribute(x.PropertyType, typeof(StepAttribute))).Step == wizardTransaction.CurrentStep);
return #object.GetValue(wizardTransaction) as TProperty;
}
This successfully renders my generic _WizardStep partial view and successfully binds up the data on POST also.
Hi everyone so I am trying to create an application using asp.net mvc with a code first database that allows the users to be able to create a blog post with as many images as they wish.I am currently trying to have the image path in one table and the heading,body text in the other table along with a foreign key to the image path.So that I can create one post with multiple images. This is my first time using multiple tables and currently I am getting an error when it reaches this line context.SaveChanges(); in the save method when I am trying to create a post and save it to the db. Thank you for any help with this issue.
An exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred in EntityFramework.dll but was not handled in user code
Additional information: An error occurred while updating the entries. See the inner exception for details
I was able to get the program to work when I was using one table but it had this issue : https://imgur.com/a/lQQ3Q
Here is the database Diagram :http://imgur.com/a/iJZGx
Query that I tried to make but am not sure where to use in my code.
var query = db.PostModel.Where(x => x.PostID == PostId).Select(x => new
{
PostID = x.PostID,
ImageId = x.ImageModel.ImageId,
ImagePath = x.ImageModel.ImagePath,
Heading = x.PostModel.Heading,
PostBody = x.PostModel.PostBody
}).FirstOrDefault();
My program
View to Create posts
#model Crud.Models.PostModel
....
#using (Html.BeginForm("Create", "Home", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<form action="" method="post" enctype="multipart/form-data">
#Html.LabelFor(model => model.ImageModel.ImagePath)
<input id="ImagePath" title="Upload a product image" multiple="multiple" type="file" name="files" />
#Html.LabelFor(model => model.Heading)
<input id="Heading" title="Heading" name="Heading" />
#Html.LabelFor(model => model.PostBody)
<input id="PostBody" title="PostBody" name="PostBody" />
<p><input type="submit" value="Create" /></p>
</form>
}
View to display posts
#model IEnumerable<Crud.Models.PostModel>
....
#foreach (var item in Model)
{
<div>#Html.DisplayFor(modelItem => item.Heading)</div>
<div>#Html.DisplayFor(modelItem => item.PostBody)</div>
<div><img class="img-thumbnail" width="150" height="150" src="/Img/#item.ImageModel.ImagePath" /></div>
}
Models
public partial class PostModel
{
[Key]
[HiddenInput(DisplayValue = false)]
public int PostID { get; set; }
public string Heading { get; set; }
public string PostBody { get; set; }
[ForeignKey("ImageModel")]
public int ImageId { get; set; }
public virtual ImageModel ImageModel { get; set; }
}
public class ImageModel
{
[Key]
public int ImageId { get; set; }
public string ImagePath { get; set; }
public string PostID { get; set; }
}
DBcontext
public class EFDbContext : DbContext
{
public DbSet<SchoolNewsModel> SchoolNews { get; set; }
public DbSet<PostModel> Posts { get; set; }
public DbSet<ImageModel> Images { get; set; }
}
Controller
public ViewResult Display()
{
return View(repository.Posts);
}
public ViewResult Create()
{
return View("Create", new PostModel());
}
[HttpPost]
public ActionResult Create(PostModel Image, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
foreach (var file in files)
{
PostModel post = new PostModel();
if (file.ContentLength > 0)
{
file.SaveAs(HttpContext.Server.MapPath("~/Img/") + file.FileName);
// post.ImagePath = file.FileName;
post.PostBody = post.PostBody;
post.Heading = post.Heading;
}
repository.Save(post);
}
}
return RedirectToAction("display");
}
public ViewResult PublicPostDisplay()
{
return View(repository.Posts);
}
Repository
public IEnumerable<PostModel> Posts
{
get { return context.Posts; }
}
public void Save(PostModel Image)
{
if (Image.PostID == 0)
{
context.Posts.Add(Image);
}
else
{
PostModel dbEntry = context.Posts.Find(Image.PostID);
if (dbEntry != null)
{
dbEntry.ImageModel.ImagePath = Image.ImageModel.ImagePath;
}
}
context.SaveChanges();
}
You need to include the full details of the error. Its the See the inner exception for details that will give you the relevant information. However that will probably not matter since your models and relationships are incorrect.
You want a PostModel to have multiple ImageModel so you need a one-many relationship and your PostModel needs have the following property
public virtual ICollection<ImageModel> Images { get; set; }
and delete the int ImageId and ImageModel ImageModel properties. In addition the ImageModel should contain public virtual PostModel Post { get; set; }
Your POST method to create a new PostModel then becomes
[HttpPost]
public ActionResult Create(PostModel post, IEnumerable<HttpPostedFileBase> files)
{
if (!ModelState.IsValid)
{
return View(post);
}
foreach (var file in files)
{
if (file.ContentLength > 0)
{
file.SaveAs(HttpContext.Server.MapPath("~/Img/") + file.FileName);
// Initialize a new ImageModel, set its properties and add it to the PostModel
ImageModel image = new ImageModel()
{
ImagePath = file.FileName
};
post.Images.Add(image);
}
}
repository.Save(post);
return RedirectToAction("display");
}
There are however multiple other issues with your code that you should address.
First, your view has nested forms which is invalid html and not
supported. You need to remove the inner <form> tag
Your editing data, so always use a view model (refer What is
ViewModel in
MVC?)
and the PostVM will include a property
IEnumerable<HttpPostedFileBase> Images and in the view, bind to it
using #Html.TextBoxFor(m => m.Images, new { type = "file", multiple
= "multiple" })
You have no validation at all, and your properties should include
validation attributes, for example, a [Required] attribute on
Heading and Body. The you need to include
#Html.ValidationMessageFor() for each property in the view.
You manual html for the inputs will not give you 2-way model binding
and prevent any client side validation. Always use the HtmlHelper
methods to generate form controls, e.g. #Html.TextBoxFor(..)
Do not save the image with just the file name (multiple users may
upload files with the same name and overwrite existing files. One
option is to use a Guid for the file name, and include a
additional property string DisplayName in ImageModel. Refer
this
answer
for an example of that approach.
I wants to make a text editor for a site to allow user to write his own text or past text from another source to create pages (like wordpress for example).
To do that i chose Jquery-Te as text editor.
My problem is that when i copy/paste a text from wikipedia for example, i got a 404.15 error. I have read that i can do some changes on the RequestLimit but i can't know how long user text can be. I can set a limit to 400000 but if user enter 500000 he will get an error. Is there another way to allow user to pass a lot of text?
My second problem is Jquery-Te generates html and my text is in fact an html code. Sometimes i cant get error like "A potentially dangerous Request.Form value was detected from the client".
Can someone help me to do what i want?
I give you my code :
View :
<form action="SaveArticle" method="post">
#Html.TextBoxFor(x => x.Article.Titre)
#Html.TextBoxFor(x => x.Article.Contenu, new { #class = "editor" })
<button type="submit" class="btn btn-info btn-circle">
<i class="fa fa-search"></i>
</button>
</form>
<script>
$(".editor").jqte();
</script>
Controller :
public ActionResult GestionDesPages(GestionDesPagesViewModel gdpvm)
{
return View(gdpvm);
}
[HttpPost]
public ActionResult SaveArticle(GestionDesPagesViewModel gdpvm)
{
Articles article = gdpvm.Article;
article.Date = DateTime.Now;
article.Auteur = "Pascal";
db.Articles.Add(article);
db.SaveChanges();
return View("GestionDesPages");
}
ViewModel :
public class GestionDesPagesViewModel
{
public Articles Article{get; set;}
}
Model :
public partial class Articles
{
public int Id { get; set; }
public string Titre { get; set; }
public string Contenu { get; set; }
public string Auteur { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<bool> Actif { get; set; }
}
Sorry For Bad English.
Thanks.
EDIT :
Thank You Nava.
The solution given by Nava helped me to resolve all my problems.
I didn't said that i uses EntityFramework. To add [AllowHttp], I used the procedure defined in this theAdd annotation to Entity Framework Generated class
To allow HTML to be inputted in your form and not get the "potentially dangerous" message add the [AllowHtml] attribute to Contenu
[AllowHtml]
public string Contenu { get; set; }
Keep in mind that when you display that field, you will probably want to Html encode to prevent a Cross site scripting problem
In my MVC-project I have different custom validation-attributes. One of them is to check the value of a property against the value of another property.
As stated in many articles, I add something like
result.ValidationParameters.Add("otherproperty", _otherPropertyHtml);
result.ValidationParameters.Add("comparetype", _compareType);
result.ValidationParameters.Add("equalitytype", _equalityType);
to the returning ModelClientValidationRule object.
My problem now is, that - if my property to check - is encapsulated in another object, validation will not work.
If I create something like
#Html.TextBoxFor(m => m.ValueOne)
#Html.TextBoxFor(m => m.ValueTwo)
validation will work fine as it renders
data-val-otherproperty="ValueTwo"
My problem is for the following
#Html.TextBoxFor(m => m.IntermediateObject.ValueOne)
#Html.TextBoxFor(m => m.IntermediateObject.ValueTwo)
This will render two textboxes with names IntermediateObject_ValueOne and IntermediateObject.ValueTwo. But still data-val-otherproperty="ValueOne" for the first textbox.
How can it be achieved, that data-val-otherproperty has always the correct name of the other property?
My thoughts are something like HtmlHelper<>.NameFor(m => ...) or something that uses reflection?
Update 1 - Added code as requested by comments
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false)]
public class CustomCompareToOther : ValidationAttribute, IClientValidatable
{
// private backing-field
private readonly string _otherPropertyName;
// constructor
public OemCompareToOther(string otherPropertyName)
{
_otherPropertyName = otherPropertyName;
}
// implementation of IClientValidatable
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var result = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.DisplayName),
ValidationType = "customcomparetoother"
};
// add the property-name so it is known when rendered for client-side validation
result.ValidationParameters.Add("otherproperty", _otherPropertyHtml); // here I would need IntermediateObject.ValueTwo instead of only ValueTwo
yield return result;
}
}
Usage at model-level would be
public class MyModel
{
[CustomCompareToOther("ValueOTwo", CompareType.NotEqual, PropertyType.String)]
public string ValueOne { get; set; }
[CustomCompareToOther("ValueTwo", CompareType.NotEqual, PropertyType.String)]
public string ValueTwo { get; set; }
}
And what I will put into my View would be something like
public class ViewModel
{
public MyModel IntermediateObject { get; set; }
}
used e.g. return View(new ViewModel()).
So, in the rendered HTML I would have an input
<input type="text" name="IntermediateObject_ValueOne" id="IntermediateObject.ValueOne" data-val-customcomparetoother-otherpropertyname="ValueTwo" />
<input type="text" name="IntermediateObject_ValueTwo" id="IntermediateObject.ValueTwo" data-val-customcomparetoother-otherpropertyname="ValueOne" />
but I need
<input type="text" name="IntermediateObject_ValueOne" id="IntermediateObject.ValueOne" data-val-customcomparetoother-otherpropertyname="IntermediateObject.ValueTwo" />
<input type="text" name="IntermediateObject_ValueTwo" id="IntermediateObject.ValueTwo" data-val-customcomparetoother-otherpropertyname="IntermediateObject.ValueOne" />
in the html so javascript-validation can fetch the other property correctly.
You can use the [Compare("PropertyName")] Data Annotation.
Example in your View Model:
[Display(Name = "New Password")]
[DataType(DataType.Password)]
public string NewPassword { get; set; }
[Display(Name = "Confirm Password")]
[DataType(DataType.Password)]
[Compare("NewPassword")]
public string PasswordConfirmation { get; set; }
Just remember to add the System.ComponentModel.DataAnnotations namespace to your using statements
I have got the radio button list in my view like below..
View:
<div class="deleteControls">
<div class="labelHead">#Html.Label("Delete")</div>
<div class="controlsAndLabels">#Html.RadioButtonFor(m => m.Submit, MVC.Models.SubmitAction.DeleteItem) #Html.Label("Delete By Item")</div>
<div class="controlsAndLabels">#Html.RadioButtonFor(m => m.Submit, MVC.Models.SubmitAction.DeleteVendor) #Html.Label("Delete By Vendor")</div>
<div class="controlsAndLabels" style="padding-left: 20px;">#Html.CheckBoxFor(m => m.IsCancelPageChecked, "Cancel Page") #Html.Label("Cancel Page")</div>
<div class="controlsAndLabels">#Html.RadioButtonFor(m => m.Submit, MVC.Models.SubmitAction.DeleteMember) #Html.Label("Delete By Member")</div>
</div>
and this is my model for that view where I am defining property for radio button
Model:
public SubmitAction Submit { get; set; }
public bool IsCancelPageChecked { get; set; }
[DeleteByItemValidator("ByItem")]
[Display(Name = "By Item")]
public string ByItem { get; set; }
[Display(Name = "By Vendor")]
public string ByVendor { get; set; }
[Display(Name = "By Member")]
public string ByMember { get; set; }
[Display(Name = "Cancel Page")]
public string CancelPage { get; set; }
and this enum for binding radio button list
public enum SubmitAction
{
DeleteItem,
DeleteVendor,
DeleteMember
}
I am doing custom validation on server side using custom validator like this below
public class DeleteByItemValidator : ValidationAttribute
{
public string DeleteByItemRadioButton { get; set; }
public DeleteByItemValidator(string deleteByItemRadioButton)
{
this.DeleteByItemRadioButton = deleteByItemRadioButton;
}
protected override ValidationResult IsValid(object currentValue, ValidationContext validationContext)
{
if (IsRadionButtonSelected(validationContext, DeleteByItemRadioButton))
{
// here I am doing validaions
}
return ValidationResult.Success;
}
// this method is giving always false even if i selected one radio button
private bool IsRadionButtonSelected(ValidationContext validationContext, string PropertyToSelect)
{
Type iType = validationContext.ObjectInstance.GetType();
object RadioButtonSelectedValue = iType.GetProperty(PropertyToSelect).GetValue(validationContext.ObjectInstance, null);//here I am getting null value
bool isChecked = Convert.ToBoolean(RadioButtonSelectedValue);
return isChecked;
}
}
My problem is that I am not checking the whether the radio button is selected or not and this method is returning false value even if I selected radio button
private bool IsRadionButtonSelected(ValidationContext validationContext, string PropertyToSelect)`
Is this way is correct to validate the radio button selection or is there any other approach please suggest any ideas.
Would any one have any idea how to check whether the radio button is selected or not
Many thanks In advance
As far as I understand, you try to validate that a radio button is checked. Why don't you add the [Required] attribute to the public SubmitAction Submit { get; set; } property and remove the IsRadionButtonSelected method?
You validator code is correct where you access the property. It is null because you are not using the ByItem in your View. Also instead of a string use a boolean. That should work.
Update:
#Html.RadioButtonFor(m => m.ByItem, Model.ByItem) #Html.Label("Delete By Item")
[DeleteByItemValidator("ByItem")]
[Display(Name = "By Item")]
public bool ByItem { get; set; }
I would do it without custom validators. Example:
Model
public class Test3Model
{
[Required]
public SubmitAction Submit { get; set; }
public bool IsCancelPageChecked { get; set; }
}
public enum SubmitAction
{
None,
ByItem,
ByVendor,
ByMember
}
View
#using (Html.BeginForm("Test3","Form"))
{
#Html.RadioButtonFor(m => m.Submit, SubmitAction.ByItem, Model.Submit== SubmitAction.ByItem ? new { Checked = "checked" } : null)
#Html.RadioButtonFor(m => m.Submit, SubmitAction.ByVendor, Model.Submit== SubmitAction.ByVendor ? new { Checked = "checked" } : null )
#Html.RadioButtonFor(m => m.Submit, SubmitAction.ByMember, Model.Submit== SubmitAction.ByMember ? new { Checked = "checked" } : null )
#Html.ValidationSummary();
<input type="submit"/>
}
Controller
[HttpPost]
public ActionResult Test3(Test3Model model)
{
if (ModelState.IsValid && model.Submit != SubmitAction.None)
{
//some actions
}
return View("Test3", model);
}
From the looks of it, the only property that is set on your object is Submit , ByItem, etc.. are never used. You can remove them I think and change the custom validator to work with Submit property only.