Hi is there a cleaner way to set default value in database first other than initialize in the partial class like below?
[MetadataType(typeof(PersonAttribute))]
public partial class person {
public person() {
isMale = true;
}
}
public class PersonAttribute
{
[Display(Name = "Title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string UserTitle { get; set; }
public bool isMale { get; set; }
}
Related
I have generic model for contact
public class Contact
{
public string Title { get; set; }
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter LastName")]
public string LastName { get; set; }
[Required(ErrorMessage = "Please enter Email")]
public string Email { get; set; }
public string Phone { get; set; }
}
Now I want to use my contact class in two models but apply the validation only on second?
public class Step1Model{
public Contact Contact{get;set;}
}
public class Step2Model{
[Requried]
public Contact Contact{get;set;}
}
How do I make it work?
I see two options here:
1 - Code to an interface which will require you to create a ContactRequired class and a ContactOptional class based upon the ContactInterface. I believe this will allow you to then have a single StepModel where you would set the StepModel.Contact property to either a new ContactRequired() or a new ContactOption(). Then when the validaiton runs for the StepModel, it will be have based upon the type of class you set for the StepModel.Contact property.
public interface ContactInterface
{
string Title { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
string Email { get; set; }
string Phone { get; set; }
}
public class ContactOptional : ContactInterface
{
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class ContactRequired : ContactInterface
{
public string Title { get; set; }
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter LastName")]
public string LastName { get; set; }
[Required(ErrorMessage = "Please enter Email")]
public string Email { get; set; }
public string Phone { get; set; }
}
public class StepModel
{
public ContactInterface Contact { get; set; }
}
Usage:
StepModel smTest = new StepModel();
ContactRequired crContact = new ContactRequired();
ContactOptional coContact = new ContactOptional();
List<ValidationResult> lErrors = new List<ValidationResult>();
smTest.Contact = coContact;
//Validate Option
if (Validator.TryValidateObject(smTest, new ValidationContext(smTest, serviceProvider: null, items: null), lErrors, true))
{
//Code should reach this as the model should be valid;
}
smTest.Contact = crContact;
//Validate Required
if (Validator.TryValidateObject(smTest, new ValidationContext(smTest, serviceProvider: null, items: null), lErrors, true))
{
//Code should not reach this as the model should be invalid;
}
2 - Create a custom required attribute which will look at another property of the Contact model (such as bool UseValidation) to determine if the required validation should even take place or if it should simply return true as the default. I am not initially providing code for this option as you would need a custom attribute for every type of validation attribute in your class. Also, I think option 1 is the better one unless you have a specific reason against it.
I have decided not to have many view models.
Here is my implementation
https://gist.github.com/cpoDesign/bc9c5980a89cfe7b0caf
i have 3 model:
1st one:
public class CreateFieldModel
{
public FieldModel fm { get; set; }
public CategoryModel cm { get; set; }
}
2nd one:
public class FieldModel
{
public string field_Name { get; set; }
public InputTypeModel itm { get; set; }
public string input1 { get; set; }
public string input2 { get; set; }
public string input3 { get; set; }
public string input4 { get; set; }
public List<InputTypeModel> inputs { get; set; }
}
3rd One:
public class InputTypeModel
{
public string inputTypeName { get; set; }
public string inputTypeDesc { get; set; }
}
2 methods:
1st One:
public List<InputTypeModel> getInputTypes()
{
var inptypes = edu.InputTypes;
List<InputTypeModel> listInputTypes = new List<InputTypeModel>();
foreach (var inpType in inptypes)
{
listInputTypes.Add(new InputTypeModel { inputTypeName = inpType.Input_Type_Name, inputTypeDesc = inpType.Input_Type_Description });
}
return listInputTypes;
}
when this method executes listInputTypes has three different values.. i check it by debugging.. so no roblem here. This methos is under the class FormManagement.. I am calling this method from the following action method:
[HttpGet]
public ActionResult createNewField(CreateFieldModel cfm, string fcode)
{
FormManagement ffm = new FormManagement();
cfm.fm.inputs = ffm.getInputTypes();
return View(cfm);
}
when cfm.fm.inputs = ffm.getInputTypes(); executes it is showing "Object reference not set to an instance of an object." message... I am quite beginner to mvc.. please help
Without knowing what you really want to achieve with cfm-parameter in your action, the only thing I can suggest is to check for null references and create new instances before you assign them:
[HttpGet]
public ActionResult createNewField(CreateFieldModel cfm, string fcode)
{
FormManagement ffm = new FormManagement();
if (cfm == null)
{
cfm = new CreateFieldModel();
}
if (cfm.fm == null)
{
cfm.fm = new FieldModel();
}
cfm.fm.inputs = ffm.getInputTypes();
return View(cfm);
}
Of course, this supposes that your not relying on incoming data through your route parameters. If you are, you need to check why the values are not getting passed in, but I'm guessing you don't need it as a parameter in the first place.
Customers.cs
public partial class Customers
{
public int sno { get; set; }
public string CustomerName { get; set; }
public string CustomerNo { get; set; }
...
// 20 more attribute too...
}
Cities.cs
public partial class Cities
{
public int sno { get; set; }
public string CityName { get; set; }
public string CityPlate { get; set; }
public string CityPhoneCode { get; set; }
}
AddCustomerViewModel.cs
public class AddCustomerViewModel
{
[Required(ErrorMessage = "Şehir seçiniz.")]
[Display(Name = "Şehir")]
public Nullable<int> CityId { get; set; }
// same with Customers.cs
public int sno { get; set; }
[Required(ErrorMessage = "Müşteri adını giriniz!")]
[Display(Name = "Müşteri Adı")]
public string CustomerName { get; set; }
[Required(ErrorMessage = "Müşteri numarası giriniz!")]
[Display(Name = "Müşteri Numarası")]
public string CustomerNo { get; set; }
...
// 20 more attribute too...
}
Controller
[Authorize(Roles = "Administrator")]
public ActionResult AddCustomer()
{
AddCustomerViewModel addCustomerViewModel = new AddCustomerViewModel();
addCustomerViewModel.Cities = entity.Cities;
return View(addCustomerViewModel);
}
[HttpPost]
[Authorize(Roles = "Administrator")]
public ActionResult AddCustomer(AddCustomerViewModel addCustomerViewModel)
{
entity.Customers.Add(GetCustomerFromViewModel(addCustomerViewModel));
entity.SaveChanges();
return View(addCustomerViewModel);
}
I m using a function that is called GetCustomerFromViewModel to convert addCustomerViewModel to Customer like below:
GetCustomerFromViewModel()
private Customers GetCustomerFromViewModel(AddCustomerViewModel addCustomerViewModel)
{
Customers customer = new Customers();
customer.CityId = addCustomerViewModel.CityId;
customer.CreatorUserId = (Guid)System.Web.Security.Membership.GetUser().ProviderUserKey;
customer.CustomerName = addCustomerViewModel.CustomerName;
customer.CustomerNo = addCustomerViewModel.CustomerNo;
customer.Description = addCustomerViewModel.Description;
...
// 20 more attribute too...
return customer;
}
But Customers class have too many variable (customerNo, CustomerName, ...) , So this is the not good way.
When I use DbContextGenerator and Add classes to dataAnnotations and then When I udated the model, dataAnnotations is deleted. (Because DbContext classes are updated, too)
How Can I use ViewModels with DataAnnotations. And effective insert operation to Db? Article, Tutorial, example or advice?
I hope I can explain.
Thanks a lot...
You may take a look at AutoMapper which will simplify the mapping logic between your domain models and view models so that you don't need to manually map each property. Other than that there's nothing wrong with your code. You are already using a view model and have a mapping layer. So your GetCustomerFromViewModel function might become:
private Customers GetCustomerFromViewModel(AddCustomerViewModel addCustomerViewModel)
{
return Mapper.Map<AddCustomerViewModel, Customers>(addCustomerViewModel);
}
or completely get rid of it and directly use the AutoMapper call in your controller action because this function no longer brings much value:
[HttpPost]
[Authorize(Roles = "Administrator")]
public ActionResult AddCustomer(AddCustomerViewModel addCustomerViewModel)
{
var customer = Mapper.Map<AddCustomerViewModel, Customers>(addCustomerViewModel);
entity.Customers.Add(customer);
entity.SaveChanges();
return View(addCustomerViewModel);
}
I'm newbie to MVC architecture.When I'm trying to update, its showing error ,Its totally strange but the data is updating.
The model item passed into the dictionary is of type 'CMS.Domain.Models.Site', but this dictionary requires a model item of type 'CMS.Web.ViewModels.SiteModel'.'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'CMS.Web.ViewModels.SiteModel', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[CMS.Web.ViewModels.SiteModel]'.
My code looks like:
ViewModels:
namespace CMS.Web.ViewModels
{
public class SiteModel
{
public SiteModel()
{
SiteStatus = new List<SelectListItem>();
}
[Key]
public int ID { get; set; }
[Required(ErrorMessage = "Site Name is required")]
[Display(Name = "Site Name")]
public string Title { get; set; }
[Display(Name = "Require Login")]
public bool RequiresLogin { get; set; }
[Display(Name = "Force HTTPS")]
public bool ForceHTTPS { get; set; }
[Display(Name = "Enable Approval")]
public bool Approval { get; set; }
[AllowHtml]
public IList<SelectListItem> SiteStatus { get; set; }
public bool Deleted { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn
{
get { return _createdOn; }
set { _createdOn = value; }
}
private DateTime _createdOn = DateTime.Now;
public string LastUpdatedBy { get; set; }
public DateTime LastUpdatedOn
{
get { return _lastUpdatedOn; }
set { _lastUpdatedOn = value; }
}
private DateTime _lastUpdatedOn = DateTime.Now;
[Display(Name = "Site State")]
public string SiteState { get; set; }
}
}
Model:
namespace CMS.Domain.Models
{
public partial class Site : Model
{
public string Title { get; set; }
public bool Approval { get; set; }
public bool RequiresLogin { get; set; }
public bool ForceHTTPS { get; set; }
public virtual string SiteStatus { get; set; }
public bool Deleted { get; set; }
}
}
Controller:
public ActionResult Index()
{
var _sites = _siterepository.FindAll();
return View(_sites);
}
public ActionResult Add()
{
var model = new SiteModel();
var _SiteStatus = _siterepository.GetSiteStatus();
foreach (var _sitestatus in _SiteStatus)
{
model.SiteStatus.Add(new SelectListItem()
{
Text = _sitestatus.StatusName,
Value = _sitestatus.StatusName.ToString()
});
}
return View(model);
}
[HttpPost]
public ActionResult Add(SiteModel _sitemodel)
{
var model = _sitemodel.ToEntity();
_siterepository.Add(model);
return View(model);
}
public ActionResult Edit(int id)
{
var model = new SiteModel();
var Site = _siterepository.Find(id);
model = Site.ToModel();
var _SiteStatus = _siterepository.GetSiteStatus();
foreach (var _sitestatus in _SiteStatus)
{
model.SiteStatus.Add(new SelectListItem()
{
Text = _sitestatus.StatusName,
Value = _sitestatus.StatusName.ToString(),
Selected = _sitestatus.StatusName == Site.SiteStatus
});
}
return View(model);
}
[HttpPost]
public ActionResult Edit(SiteModel _sitemodel)
{
var model = _sitemodel.ToEntity();
_siterepository.Update(model);
return View(model);
}
I'm struggling to resolve this , please help.
Check your View's model declaration. It is expecting an enumerable list (IEnumerable<CMS.Web.ViewModels.SiteModel>), but you are passing it a single instance of CMS.Web.ViewModels.SiteModel
I've got a ViewModel for adding a user with properties: Email, Password, ConfirmPassword with Required attribute on all properties. When editing a user I want the Password and ConfirmPassword properties not to be required.
Is there a way to disable validation for certain properties in different controller actions, or is it just best to create a seperate EditViewModel?
I like to break it down and make a base model with all the common data and inhierit for each view:
class UserBaseModel
{
int ID { get; set; }
[Required]
string Name { get; set; }
[Required]
string Email { get; set; }
// etc...
}
class UserNewModel : UserBaseModel
{
[Required]
string Password { get; set; }
[Required]
string ConfirmPassword { get; set; }
}
class UserEditModel : UserBaseModel
{
string Password { get; set; }
string ConfirmPassword { get; set; }
}
Interested to know if there is a better way as well although this way seems very clean an flexible.
You could write a custom attribute that can test a condition and either allow an empty field or not allow it.
The below is a simple demo i put together for the guys here. You'll need to modify to suit your purposes/
using System.ComponentModel.DataAnnotations;
namespace CustomAttributes
{
[System.AttributeUsage(System.AttributeTargets.Property)]
public class MinimumLength : ValidationAttribute
{
public int Length { get; set; }
public MinimumLength()
{
}
public override bool IsValid(object obj)
{
string value = (string)obj;
if (string.IsNullOrEmpty(value)) return false;
if (value.Length < this.Length)
return false;
else
return true;
}
}
}
Model;
using CustomAttributes;
namespace Models
{
public class Application
{
[MinimumLength(Length=20)]
public string name { get; set; }
}
}
Controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Application b)
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (ModelState.IsValid)
{
return RedirectToAction("MyOtherAction");
}
return View(b);
}
enter code here