Create ModelStateErrorMessage in mvc2 - asp.net-mvc-2

I create Models for manually showing error. For Example, I have Organization Model. In this i have fields like,
Name
EmailAddress
Mobilenumber
IndustryId.
In the above if any item is not fill in user page, It shows "Name is required" like that.
My code in Model
public class Organization_Validation
{
[Required(ErrorMessage = "Name is required")]
[StringLength(200, ErrorMessage = "Name cannot exceed 50 characters")]
public string Name { get; set; }
[Required(ErrorMessage = "Industry is required")]
[Range(1, int.MaxValue, ErrorMessage = "Industry is required")]
public int IndustryId { get; set; }
[Required(ErrorMessage = "MobileNumber is Required")]
public string MobileNumber { get; set; }
[Required(ErrorMessage = "Email Address is required")]
public string Email { get; set; }
}
Here I want to check Mobilenumber and Email address. Anyone of these two can enter. If user enter Mobilenumber without email means it should not showing error. it will update. How to do this?

You may take a look at FluentValidation.NET which allows you to replace the declarative Data Annotations (which are very limited in such scenarios) with imperative validation rules. It has a great integration with ASP.NET MVC and in addition to that it allows you to easily unit test your validation rules.

Related

How to change dynamically entity property's display name attribute at runtime

Entity property look like this:
[Display(Name = "Email")]
public string Email { get; set; }
its for English,
when user select another language this attribute will change at runtime
[Display(Name = "DisplayAnotherSomething")]
public string Email { get; set; }

How do I limit the columns that are returned by web api?

How do I limit the columns that are returned by web api & entity framework?
I would appreciate as much info as possible as I am still a newbie ;)
My Controller:
//GET: api/Creditors
public IQueryable<Creditor> GetCreditors()
{
return db.Creditors;
}
My Class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace PurchaseOrders.Models
{
public class Creditor
{
[Key]
public int CreditorID { get; set; }
[MaxLength(10, ErrorMessage = "Maximum of 10 characters")]
public string CRKEY { get; set; }
[Display(Name = "Business Name")]
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string BusinessName { get; set; }
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string Address { get; set; }
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string City { get; set; }
[MaxLength(4, ErrorMessage = "Maximum of 4 characters")]
public string State { get; set; }
[MaxLength(4, ErrorMessage = "Maximum of 4 characters")]
public string Postcode { get; set; }
[MaxLength(15, ErrorMessage = "Maximum of 15 characters")]
public string Phone { get; set; }
[MaxLength(15, ErrorMessage = "Maximum of 15 characters")]
public string Fax { get; set; }
[MaxLength(60, ErrorMessage = "Maximum of 60 characters")]
public string Email { get; set; }
[MaxLength(60, ErrorMessage = "Maximum of 60 characters")]
public string Website { get; set; }
[MaxLength(30, ErrorMessage = "Maximum of 30 characters")]
public string ContactName { get; set; }
[MaxLength(15, ErrorMessage = "Maximum of 15 characters")]
public string ABN { get; set; }
[Display(Name = "Registered for GST")]
public bool RegisteredForGST { get; set; }
}
}
This currently returns:
[{"CreditorID":1,"CRKEY":"test1","BusinessName":"test1","Address":"7 Smith Street","City":"Melbourne","State":"VIC","Postcode":"3000","Phone":null,"Fax":null,"Email":null,"Website":null,"ContactName":null,"ABN":"null","RegisteredForGST":true},{"CreditorID":2,"CRKEY":"test2","BusinessName":"test2","Address":"10 Smith Street","City":"SYDNEY","State":"NSW","Postcode":"2000","Phone":null,"Fax":null,"Email":null,"Website":null,"ContactName":null,"ABN":"null","RegisteredForGST":true}]
This is the result I want (only the "CreditorID" & "BusinessName"):
[{"CreditorID":1,"BusinessName":"test1"},{"CreditorID":2,"BusinessName":"test2"}]
In your question you're showing the json output of the query, so I assume you're making the GET request from Javascript. As you're using the IQueryable as the type of the return value from your API method, you should be able to take advantage of the OData support that WebApi provides so that you can issue an OData query to select just the columns you want. This this article for more detail on the OData support.
So firstly, the javascript side, assuming jQuery for ease of answering:
$.get('api/Creditors?$select=CreditorId,BusinessName', onSuccess)
The column names you want are specified in a comma separated list in the $select argument. (The onSuccess is a callback function you would define which would be passed the data that comes back from the API. See the jQuery documentation for more details.)
On the server side, you might need to derive your controller from ODataController instead of ApiController and you will need to add either the [Queryable] or the [EnableQuery] attribute to your GetCreditors() method depending on the version of WebApi you are using.
There is another bit of configuration you have to add if you find that you do need to inherit from ODataController to make this work, and that is to configure the OData endpoint. To do this you will need code similar to the following:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Creditor>("Creditors");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null, // or "api" ?
model: builder.GetEdmModel());
}
}
Somewhere in your web startup code (e.g. Application_Start) you will need to call this as follows:
GlobalConfiguration.Configure(WebApiConfig.Register);
Depending on how you've set your project up, some of this latter configuration might not be necessary as it will already be done, but I thought I'd mention it for good measure. Have a look at this page for more details.
This can be done using projection, here is sample using anonymous type:
db.Creditors
.Select(x => new {
x.CreditorID,
x.BusinessName,
})
.ToArray()
This will result in query to database which will get only two fields you need wrapped in anonymous class. You can return it directly from your WebAPI controller with JSON result.
If you need to pass result (which is of type SomeAnonymousClassICanNotReference[]) between layers, you can either use dymanic keyword (not a good option actually), or use your custom class like Select(x => new MyClass { Id = x.CreditorID ...
There are several different ways to handle this requirement without OData. I tend to use a projection query (as Lanorkin mentioned in his answer). Here are some examples.
1. Return a dynamic type from your WebAPI controller:
This is the quickest and easiest method. Some would argue that dynamic return types are sloppy, but they get the job done.
[HttpGet]
public dynamic GetCreditors() {
return db.Creditors
.Select(x => new {
x.CreditorID,
x.BusinessName,
}).ToArray()
}
2. Use an explicit return type in your controller:
This works with WebAPI as well as WCF which does not allow dynamic return types. This is a "better" approach if your standard practice is to use static return types.
Create a class for your return type:
public class CreditorResult {
public int CreditorID { get; set; }
public string BusinessName { get; set; }
}
Then your API method would look like this:
[HttpGet]
public CreditorResult[] GetCreditors() {
return db.Creditors
.Select(x => new CreditorResult() {
x.CreditorID,
x.BusinessName,
}).ToArray()
}
3. Use model attributes to control the output fields:
The current version of WebAPI uses JSON.NET as its serializer, and older versions can be set up to use it too. You can specify data attributes on your model to tell JSON.NET which properties to include or to ignore.
If you're using the code-first approach to Entity Framework then you can add the attributes directly to your class. If you're using the database-first approach (code generation) then it's safest to put your attributes in a Metadata class. http://www.ozkary.com/2015/01/add-data-annotations-to-entity.html
If you only want to include a few fields, you should add [DataContract] to the class and [DataMember] to the properties. Only the properties with [DataMember] will be included in the output. For example, the following would only return CreditorID and BusinessName:
[DataContract]
public class Creditor
{
[DataMember]
[Key]
public int CreditorID { get; set; }
[DataMember]
[Display(Name = "Business Name")]
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string BusinessName { get; set; }
...
If you want to include most of your fields and ignore a few, the easier option is to add [JsonIgnore] to the properties that you wish to hide.
public class Creditor
{
[Key]
public int CreditorID { get; set; }
[JsonIgnore]
[MaxLength(10, ErrorMessage = "Maximum of 10 characters")]
public string CRKEY { get; set; }
[Display(Name = "Business Name")]
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string BusinessName { get; set; }
...
There are a lot of other ways to fine-tune the output. Check out http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size for more details.

Auto generate models in mvc 4 database first?

I created an mvc 4 web project using database first and entity framework but was surprised to see that default models were not generated automatically, is there a way to create them from my .edmx file or are there any other possibilities to save hand coding them?
Any help would be much appreciated
UPDATE:
Sorry, should have mentioned I am looking for a solution to generate simple models with basic methods such as :
public class EditUserModel
{
public int ID { get; set; }
[Required(ErrorMessage = "Forename is required")]
public string Forename { get; set; }
[Required(ErrorMessage = "Surname is required")]
public string Surname { get; set; }
[Required(ErrorMessage = "Username is required")]
public string Username { get; set; }
}
I ended up making a SQL query to generate a simple mvc model from my tables.

EF code first uncertainty principle - referred entities may not get loaded

With automatic database recreation, it is uncertain whether referred entities will get loaded or not.
The context is EF CTP 5 and ASP.NET MVC 2. In the global.asax a database initializer is set that forces recreation of the database every time the application starts up.
Successfully retrieving an entity from a context in a controller action may still cause null reference errors when traversing references even if the references are marked as required (not null in the database). Turning off lazy loading does not make any difference.
This behaviour cannot be reproduced reliably but was observed on two different workstations (XP, 7) using Cassini.
Below are the models. Null reference exception is thrown when trying to access the NewsProvider property of the NewsFeed object. It makes no difference taking off the virtual qualifier.
public class NewsProvider
{
public int Id { get; set; }
[Required(ErrorMessage = "Please enter a name")]
[StringLength(50, ErrorMessage = "The name is too long")]
public string Name { get; set; }
}
public class NewsFeed
{
public int Id { get; set; }
[Required(ErrorMessage = "Please enter a name")]
[StringLength(50, ErrorMessage = "The name is too long")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter a URL")]
[StringLength(300, ErrorMessage = "The URL is too long")]
public string Url { get; set; }
[Required(ErrorMessage = "Please enter a news provider")]
public virtual NewsProvider NewsProvider { get; set; }
}
This is just a guess, but complex types can NEVER be null. So if you have any reference to a complex type (ICollection) you should initialize them from the Entity constructor.
Example:
public class NewsProvider
{
public int Id { get; set; }
[Required(ErrorMessage = "Please enter a name")]
[StringLength(50, ErrorMessage = "The name is too long")]
public string Name { get; set; }
}
public class NewsFeed
{
public NewsFeed() {
//Never allow NewsProvider to be null
NewsProvider = new NewsProvider();
}
public int Id { get; set; }
[Required(ErrorMessage = "Please enter a name")]
[StringLength(50, ErrorMessage = "The name is too long")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter a URL")]
[StringLength(300, ErrorMessage = "The URL is too long")]
public string Url { get; set; }
[Required(ErrorMessage = "Please enter a news provider")]
public virtual NewsProvider NewsProvider { get; set; }
}
For more info, here is a great blog post:
http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx

MVC Validation in Model

I'm currently using DataAnnotations to validate my MVC 2 app. However, I've ran into a small problem.
I currently have an object of type User which has a number of properties. All of which are required.
public class User
{
[Required(ErrorMessage = "Username is required")]
public string Username { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "First name is required")]
public string Firstname { get; set; }
[Required(ErrorMessage = "Last name is required")]
public string Lastname { get; set; }
}
At signup, these are all mapped using the modelbinder and everything works great. However, on the "edit my detail" page only Firstname, Lastname and Email can be updated.
Whenever the view posts back and modelbinding is applied I'm getting an alert Username/Password is a required field. Even though it is not required at this point. I've thought of two ways to get around this neither of which I feel are suitable (but may be wrong)
1: Create a custom viewmodel. This will work fine, but data annotations will need to be applied to this viewmodel meaning duplicate validation on the model and the user object.
2: Include all the fields in the renderd view and post them back. This has security risks, seems really messy and wouldn't scale well to complex viewmodels.
Can anyone recommend a best practice for this situation?
There was similar question recently:
Needing to copy properties before validation. In response I have suggested creating custom ModelBinder for usage only in this particular action, and I still believe it's a best solution.
DataType
Specify the datatype of a property
DisplayName
specify the display name for a property.
DisplayFormat
specify the display format for a property like different format for Date proerty.
Required
Specify a property as required.
ReqularExpression
validate the value of a property by specified regular expression pattern.
Range
validate the value of a property with in a specified range of values.
StringLength
specify min and max length for a string property.
MaxLength
specify max length for a string property.
Bind
specify fields to include or exclude when adding parameter or form values to model properties.
ScaffoldColumn
specify fields for hiding from editor forms.
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Employee.Models
{
[Bind(Exclude = "EmpId")]
public class Employee
{
[ScaffoldColumn(false)]
public int EmpId { get; set; }
[DisplayName("Employee Name")]
[Required(ErrorMessage = "Employee Name is required")]
[StringLength(100,MinimumLength=3)]
public String EmpName { get; set; }
[Required(ErrorMessage = "Employee Address is required")]
[StringLength(300)]
public string Address { get; set; }
[Required(ErrorMessage = "Salary is required")]
[Range(3000, 10000000,ErrorMessage = "Salary must be between 3000 and 10000000")]
public int Salary{ get; set; }
[Required(ErrorMessage = "Please enter your email address")]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
[MaxLength(50)]
[RegularExpression(#"[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}", ErrorMessage = "Please enter correct email")]
public string Email { get; set; }
}
}