I'm wanting to check if I can send a message from a Model to a Controller, I'll explain.
So I have a Model
public class Car()
{
public int Id { get; set; }
public string Make { get; set; }
}
So when a user adds a new Car, I could make it required by using Fluent API or the [Required] annotation.
But what if I wanted to make sure I had only certain characters in there, so I wouldn't want the percentage symbol in there (unless there are any cars out there?!).
So I thought I'll use a constructor:
public class Car()
{
public Car(string _name)
{
if(this.Make.Contains("%"))
{
//Let the user know this isn't valid there is an error
}
}
public int Id { get; set; }
public string Make { get; set; }
}
I usually place the error logic in the Controller. So I would have
public ActionResult AddCar(Car car)
{
if(car.Make.Contains("%"))
{
//let user know this is not valid
}
if(ModelState.IsValid)
{
}
///
}
But then I thought, I'm never going to want to have a car Make with a % sign (I've picked on % sign, but actually there is a host of validation I would use, such as a list containing invalid characters), and every place in which I allowed for a user to add a car, I would duplicate the validation code, which just felt inefficient.
Maybe producing a the error checking in the controller is the correct way?
Again for clarity. The question, is there a way to pass a message from a Model to a Controller, which I can then pass to the User's view?
Kind regards
You should not use validation logic in your controller, we have DataAnnotations which allows us to validate model's properties value.
for your purpose you can use RegularExpression validator for this.
Refer to this Link for more details
Related
I'm currently working on a content editor that can be used for multiple types of content, where a developer could specify their own model. For example, a model might look like this:
public class ImageWithCopyWidgetModel : WidgetModel, IWidgetModel
{
public string ImageUrl { get; set; }
public string ImageAltText { get; set; }
public string HeaderText { get; set; }
public string BodyContent { get; set; }
}
On the editor side, I have a view model that looks like:
public class EditContentViewModel<TModel> where TModel : IWidgetModel
{
public int Id { get; set; }
public string Name { get; set; }
public TModel WidgetModel { get; set; }
}
I have the binding on the GET/form display side working fine. My issue comes with getting the model binder to accept the data on the POST? I've tried the following, but each returns null for model.WidgetModel:
// Option 1
EditContent(int pageId, int id, EditContentViewModel<dynamic> model)
// Option 2
EditContent(int pageId, int id, EditContentViewModel<object> model)
// Option 3
EditContent(int pageId, int id, EditContentViewModel<IWidgetModel> model)
Note, for testing purposes, I tried explicitly setting the type of WidgetModel to a concrete class (the ImageWithCopyWidgetModel noted above) and that works.
I'm really trying to avoid having to use Request.Form here as its going to limit future plans for this implementation.
What you're wanting is not possible, at least out of the box. On post, all the modelbinder has is a bunch of key-value pair string. What informs its decision about how to bind those values to something useful is the action param(s). Specifically, it has no way of knowing that it should actually create an instance of ImageWithCopyWidgetModel when you're binding to EditContentViewModel.
Also, the modelbinder is designed to discard values it doesn't know what to do with. That means that it's unfortunately not even possible to cast to ImageWithCopyWidgetModel after the fact, because all properties not present on EditCopyViewModel would have been discarded by that point.
Your best bet is a custom model binder, but the implementation of that is too broad for the scope of Stack Overflow. I suggest you refer to the documentation.
I want to add a new property on my class, make it strongly typed so I can use it in my views and controllers, I've tried to inherit the properties, but Entity Framework or C# throws me errors...
I have this class:
public class Patient
{
public int Id { get; set; }
public string Message { get; set; }
public string FirstName { get; set; }
.....
}
which has a lot more properties in it, but shortened here.
I have a razor view, which is uses 'Patient' as it's model
using model Project.Models.Patient
So I had completed my view (or so I thought) and was asked to add functionality in the view. The functionality is to send a POST using a form of a 'Message' (a simple textarea in html). I've already got all the details I want, but this new 'Message'
So I thought, because I don't want this field in the database I could add it like this:
public class Patient
{
public int Id { get; set; }
public string Message { get; set; }
public string FirstName { get; set; }
[NotMapped]
public string Message { get; set; }
.....
}
But I'm not a fan of this, it doesn't relate to the Patient in any other way.
So I thought I could change my model in razor to something like this:
#model Project.Models.DTOs.PatientMessage
and inherit the Patient class and all it's properties (so I don't have to retype and copy past the fields again) and the new PatientMessage class would look like this:
public class PatientMessage : Patient
{
public string Message { get; set; }
}
But when I refresh my application, I receive a message stating the Application Database Context has changed, and I have to update this. I don't want to update my database, and I can't really see why I need to, it's an extra field which I don't want to include in my database.
So then I decided to make this class an 'abstract' class
public abstract class PatientMessage : Patient
{
public string Message { get; set; }
}
When I refreshed my page this time, I saw no need to update the Database, great I thought, and when I went near a page where the model was
#model Project.Models.Patient
I received this message
The abstract type 'Project.Models.DTOs.PatientMessage' has no mapped descendants and so cannot be mapped. Either remove 'Project.Models.DTOs.PatientMessage' from the model or add one or more types deriving from 'Project.Models.DTOs.PatientMessage' to the model.
MY QUESTION
Can I include this one field, without placing it on the Patient class, ideally without having to update models in my razor views, or would I have to change the models in the views and controllers and update the information to include the message and map all the details from a 'PatientMessage' to a 'Patient'
Please let me know if you need any further information.
Regards
I have a model described as below:
public class Projet
{
public int ProjetId { get; set; }
public int SeqNumber{ get; set; }
public string Code{ get; set; }
public string Description { get; set; }
public bool Std{ get; set; }
public bool Archive { get; set; }
}
I have a create view to let a user create a new project, and I must let the SeqNumber field free so the user can input whatever number he wants.
However, I must return an error if the SeqNumber choosen is already taken.
I'm not sure how to implement this. Should I do some validation in my ProjetsController/Create action ? From what I can find, validating stuff in the controller is a bad practise, but I can't think of where to implement validation when it depends on other members of the same class.
Would coding a custom validator for MVC considered a good practise?
Thanks !
You can use this in your http post action method which handles the form submit
[HttpPost]
public ActionResult Create(Projet model)
{
var exist = db.Projects.Any(s=>s.SeqNumber===model.SeqNumber
&& s.ProjectId!=model.ProjectId);
if(exist)
{
ModelState.AddModelError(string.empty,"Sequence number is already in use");
return View(model);
}
// to do : Continue with your save
}
Now when user submits the form, if the sequence number is being used for any other project, it will throw a validation message. Make sure you are using the Validation summary helper in your view to render the validation error message.
#model Project
#Html.ValidationSummary(false)
#using(Html.BeginForm())
{
<!-- your existing code goes here-->
}
Now to give a nice user experience, you may take advantage of the Remote validation feature. What it does is, when user takes the focus out from the input, it makes an ajax call to server to check whether your SequenceNumber exist in db. Based on the result, the validation messages will be shown to the user.
To do this, decorate your property with the Remote attribute.
[Required]
[System.Web.Mvc.Remote("CheckSeqNumber", "Project",
ErrorMessage = "SeqNumber is already used!")]
public int SeqNumber { get; set; }
Now make sure you have an action method called CheckSeqNumber which returns either true or false as a json response.
public ActionResult CheckTagName(int SeqNumber)
{
var exist= !db.Projects.Any(g => g.SeqNumber == SeqNumber);
return Json(exist,JsonRequestBehavior.AllowGet);
}
Also make sure you have the relevant javascript files loaded to do this unobtrusive validation.
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
Another option is to write a custom validation attribute which does this check for you (if you do not like that check in the action method). Here is an SO post explaining how to do it.
I'm new at ASP.NET MVC web framework. My database is compound of a single model class("Movie"). I need to validate user's from entering existing data, for instance, a database row could be:
Title - "Indiana Jones and the lost Arc"
Price - $10.00
If another user tries to insert into the database the same data above, provide an error message and prevent from submitting the form collection.
First of all, I think that your question need a "program as answer" but I'll try to suggest you from where to start for working with validation. Suppose you have this model:
class Movie {
public Guid Id { get; set; }
[Required(ErrorMessage="Title is required.")]
[Remote("UniqueTitle", "Validation")]
public String Title { get; set; }
[Required(ErrorMessage="Price is required.")]
public float Price { get; set; }
}
You can decorate it for "simple validation" using Data Annotation. I've used a specific attribute, called Remote.
This attribute allow you to define a custom, server-side, logic to validate the model.
Now, you can create a validation controller where check that provided value is not already in use:
class ValidationController : Controller {
private IDbContext db = ...;
public ActionResult UniqueTitle(String title) {
var item = db.Movies.FirstOrDefault(m => m.Title.Equals(title));
return Json(item == null, JsonRequestBehavior.AllowGet);
}
}
Now you are ready to validate your model.
I hope this can help.
please help me with asp.net MVC 2 application.
I have class:
public class Account
{
[Required(....)]
[RegularExpression("....")]
public string AccountCode{ get; set; }
public string BankName{ get; set; }
}
And another one:
public class BankPageModel
{
public bool AccountRequired {get; set; }
public Account NewAccount {get;set;}
}
Imagine I have page and form on it with 2 text boxes (AccountCode and BankName) and check box (AccountRequired). So when I post the form, if check box is checked, I want to validate AccountCode to be required and to fit regular expression. But if it is not checked, I just want to ignore those text boxes and to post the form. But Required and RegularExpression attributes cannot be used then, they are preventing it. I could make class attribute, but what if I have more textboxes with similar validation, I don't want to make class attribute for each of them...
What do you think? Thanks in advance.
The best way to do this on the server side, is to have your model implement IValidatableObject and then do the following:
public class BankPageModel : System.ComponentModel.DataAnnotations.IValidatableObject
{
public bool AccountRequired { get; set; }
public Account NewAccount { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// only perform validation here if account required is checked
if (this.AccountRequired)
{
// check your regex here for account
if (!RegEx.IsMatch(this.NewAccount.AccountCode, "EXPRESSION"))
{
yield return new ValidationResult("Error");
}
}
}
}
Doing things this way helps keep your controllers lean and encapsulates all validation logic in your model. This method could also be verified client side with unobtrusive javascript.
You don't need to use DataAnnotations to perform validation, they just make things easier for common validation scenarios (and you can get client side JavaScript validation for free too).
You can always perform the validation in C# code in your Controller action like below:
public ViewResult BankPageAdd(BankPageModel model)
{
if(model.AccountRequired &&
(String.IsNullOrWhiteSpace(model.Account.AccountCode) || !Regex.IsMatch(model.Account.AccountCode, "PATTERN HERE"))
ModelState.AddModelError("NewAccount.AccountCode", "ERROR MESSAGE HERE");
//remainder of your controller action code here
}
And the javaScript version:
function validateAccountCode() {
var bCkd = document.getElementById("ckbxAccountRequired").checked;
if (bCkd) {
var accountCode = document.forms[0].elements["AccountCode"].value;
if(!accountCode.match(yourRegEx) || accountCode==""){
alert('Please fill in the Account Code');
return false;
}
return true;
}
return true;
}