Tuesday, February 28, 2017

Data Annotation Examples


A few Data Annotations that come in handy when decorating models
  • [Key] Useful if the key on the table is not explicitly obvious or declared
  • [Required]  Forces a value - uses a default error message of "Field Name is Required"
  • [Display(Name = "Phone")] This is what shows on a LabelFor
  • [RegularExpression(@"^[^<>*]+$", ErrorMessage = "No Special characters allowed")] Regex expressions can provide lots of flexibility
  • [DataType(DataType.EmailAddress)] Various DataTypes are available[DataType(DataType.PostalCode)]
  • [MaxLength(30, ErrorMessage = "City cannot exceed 30 characters")]
    Maxlength annoations do not stop entry at 30 characters like the client side version but does throw an error if field exceeds # of charaters

       

Monday, January 23, 2017

Excel file from Controller

Very easy way to create Excel quickly....

public void ExcelResults(int id)
{
         Business.Agreement_Provider agr = new Business.Agreement_Provider();
         List<MyModel> model = new List<MyModel>();
         var agreements = agr.getExpiringAgreements(id);
         model = agreements.ToList();
         model.OrderBy(p => p.My_Number);

         Export export = new Export();
         export.ToExcel(Response, model);
       
}

Two methods  - Call the first one from the page and then it uses the public
Export class to return a file. The nice thing about the Export class is that we are passing our model in as an object   - this allows us to reuse this same class for any model.

public class Export
        {
            public void ToExcel(HttpResponseBase Response, object myList)
            {
                var grid = new System.Web.UI.WebControls.GridView();
                var thisDate = DateTime.Now.ToShortDateString().Replace("/","_");
                grid.CssClass = "table table-bordered table-striped table-condensed";
                grid.DataSource = myList;
                grid.DataBind();
                Response.ClearContent();
                Response.AddHeader("content-disposition",
                  "attachment; filename=MyFileName_" + thisDate + ".xls");
                Response.ContentType = "application/excel";
                StringWriter sw = new StringWriter();
                HtmlTextWriter htw = new HtmlTextWriter(sw);
             
                grid.RenderControl(htw);
                Response.Write(sw.ToString());
                Response.End();
            }
        }

Linq list with counts

 Return a list with item counts such as

Apples - 3
Oranges -7
Berries - 15

public List<SelectListItem> MyFruityList()
{
//Declare a new list of items
List<SelectListItem> items = new List<SelectListItem>();
 int totalcount = 0;
//get all your objects and add to a variable
var allfruits= prog.getallFruits();

//This next method returns a FruitId, FruitName and FruitCount
var pg = prog.getExpiringFruitCounts().OrderByDescending(p => p.FruitCount);

var alljoined = (from a in allfruits
                                 join c in pg
    on new { a.FruitId, a.FruitName } equals new { c.FruitId, c.FruitName } into joinedData
    from c in joinedData.DefaultIfEmpty() group a by new { a,c } into ord
                               
                                 select new SpecialFruit_DTO
                                 {
                                     Fruitid = ord.Key.a.FruitId,
                                     FruitName =ord.Key.a.FruitName ,
                                     OnHandCount=  ord.Key.c.FruitCount
                                   
                                 } ).ToList();
           
foreach (var p in alljoined)
                {
int count= p.OnHandCount== null ? 0 : p.OnHandCount;
 items.Add(new SelectListItem { Text = p.FruitName + "  [" + count  + "]", Value =p.FruitId.ToString() });
                }

            }

Meta Data - Annotating Models

One of the issues with using Entity Framework is that you may want some special annotation but you don't want to use a DTO or other object outside of EF.

One way to afford you the opportunity to Annotate on the original EF model is to extend with a partial class of meta data.

In your Data Models folder (or really anywhere in your data project) you would add a class (Partial Classes) that would contain empty pointers to your data classes - (in my tt files I have a company class and a systemUser class which represent models from the tables in my database):

PartialClasses.cs

using System.ComponentModel.DataAnnotations;

namespace MySite.Data
{

    [MetadataType(typeof(systemUsersMetadata))]
    public partial class systemUser
    {
    }
    [MetadataType(typeof(companyMetadata))]
    public partial class company
    {
    }
}

Once you have this setup you can begin to annotate! Create a systemUsersMetadata.cs class and you can now add annotations while still using your original EF model - and you don't have to annotate everything  - just the fields you want.

public class systemUsersMetadata
    {
        [RegularExpression(@"^[^<>*]+$", ErrorMessage = "Special characters are not allowed")]
        [Required(ErrorMessage = "First Name is required")]
        [MaxLength(30, ErrorMessage = "First Name may not exceed 30 characters")]
        [Display(Name = "First Name")]
        public string firstName { get; set; }

        [RegularExpression(@"^[^<>*]+$", ErrorMessage = "Special characters are not allowed")]
        [Display(Name = "Last Name")]
        [Required(ErrorMessage = "Last Name is required")]
        [MaxLength(30, ErrorMessage = "Last Name may not exceed 30 characters")]
        public string lastName { get; set; }

        [Display(Name = "Middle Name")]
        public string middleName { get; set; }


        [Display(Name = "Email")]
        [DataType(DataType.EmailAddress)]
        [Required(ErrorMessage = "Email is required")]
        [MaxLength(60, ErrorMessage = "Email Address may not exceed 60 characters")]
        public string email { get; set; }

        [Display(Name = "Phone")]
        [RegularExpression(@"^[^<>*]+$", ErrorMessage = "Special characters are not allowed")]
        [Required(ErrorMessage ="Phone is required.")]
        [MaxLength(15, ErrorMessage = "Phone number may not exceed 15 characters")]
        public string phone { get; set; }
}

Tuesday, December 13, 2016

Custom Validation

Example validating within a data layer 

I was having a conversation with a new .net colleague the other day and he indicated that he had learned about custom validators and was all excited about validating some properties within DTO's .  The validator pattern he was using however was designed for the Web app and not the data layer where most of our models and all of our DTO's resided.  So I showed him an alternative way to accomplish the same thing without corrupting his data layer by pulling in System.Web.  Below are both methods.


Here is the method he initially wanted to plop into the data project  - more aptly designed to work with a  web application  - since this method of course depends on System.Web - it would not be compatible with data layer.  Both methods accomplish the same thing.


namespace MyProject.ModelValidation
{
   [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
   public sealed class ValidFutureDate : ValidationAttribute, IClientValidatable
   {
        
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                DateTime _date = Convert.ToDateTime(value);
                if (_date < DateTime.Now)
                {
                    return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                }
            }
            return ValidationResult.Success;
        }
     

      public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
      {
         ModelClientValidationRule mvr = new ModelClientValidationRule();
         mvr.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
         mvr.ValidationType = "validfuturedate";
         return new[] { mvr };
      }
   }
}

Here is the method I rewrote for him.




namespace MyProject.Data
{
    public class ValidateDateResult : ValidationAttribute
    {
        private readonly DateTime _minValue = DateTime.UtcNow;
        private readonly DateTime _maxValue = DateTime.UtcNow.AddYears(20);

        public override bool IsValid(object value)
        {
            DateTime val = (DateTime)value;
            return val >= _minValue && val <= _maxValue;
        }

        public override string FormatErrorMessage(string name)
        {
            return string.Format(ErrorMessage, _minValue, _maxValue);
        }
    }
}

Tuesday, December 6, 2016

Linq - Linked Tables on Common identifier

Lets say you have Table A and Table B and a Table which has a sole function of joining the two - not so uncommon.  You want all the records from Table A and corresponding records from Table B but you don't want to include your join table.

Using Entity Framework you could do something like this. The highlighted row is what I want to draw your attention to.  See that instead of a true join I have selected the collection of TableB records in Table A    A.TableB



public IQueryable<Network> getjoinedData(int Id)
        {
            var myRequest = (from A in db.TableA
                             from B in A.TableB
                             join C in db.TableC on B.programId equals c.programId

                             where A.active == true
                             && B.active == true
                             && C.active == true
                             select n);
   
            return myRequest;
}


Wednesday, November 16, 2016

Hex Icons

Hex Icons are so much better than using images for buttons.

In this example I am using the Hex code to illustrate the magnifying glass inline with an input texbox. I have used inline styles so that it is easy to see the styles I applied. The Hex code is the value of the input and shows the icon inline with the texbox to the right.


<div style="background-color: white; height: 30px; width: 258px;">

@Html.TextBox("SearchTerm", null, new { @placeholder = "Enter Search Term", @style="width:220px;" })

<input id="searchBtn" style="border: 0; cursor: pointer; display: inline; height: 100%; margin-right: 0px; margin-top: 0px; width: 30px;" type="submit" value="&#x1f50e;" />

</div>




I like this site for finding Hex Icons: http://graphemica.com/

Including a little lock on Admin sections
🔒 is nice