Wednesday, July 24, 2013

Count and limit characters with Javascript

I recently had to limit the length of a text area to 250 characters so I first created the script below:

<script type="text/javascript">
            var count = 250;
            function limiter() {
                var tex = document.MyForm.MyField.value;
                var len = tex.length;
                if (len > count) {
                    tex = tex.substring(0, count);
                    document.MyForm.MyField.value = tex;
                    return false;
                }
                document.MyForm.CharsLeft.value = count - len; //display the chars left
                
            } 
</script>

After that I added the function to the onKeyUp event of the Text area. However I noticed that the count was incorrect. First of all it counted incorrectly and second, if you kept the button pressed it did not show on the page the correct number of chars left.

To fix this I also added the function to the onKeyDown event of the Text area. After that, everything was ok.


<td colspan="2">@Html.TextAreaFor(model => model.MyField, 4, 130,
                         new
                         {
                             onChange = "document.MyForm.MyField.value=this.value;",
                             onKeyDown = "limiter()",
                             TextMode = "MultiLine",
                             onKeyUp = "limiter()",
                             MaxLength = "250",
                             MaxChars = "250",
                             Rows = "2",
                             Cols = "125"
                          })
 </td>

Tuesday, March 5, 2013

Serialize object to XML file or XML to object (Deserialize)

This code snippet shows how to serialize an object to an XML file.


            XmlSerializer xs = new XmlSerializer(MyObject.GetType());
            MemoryStream ms = new MemoryStream();
            xs.Serialize(ms, MyObject);


            StreamWriter sw = System.IO.File.CreateText("C:\\tmp\\custData.xml");
            ms.Position = 0;
            StreamReader sr = new StreamReader(ms);
            string theContent = sr.ReadToEnd();

            sw.Write(theContent);
         
         
            sw.Close();
            sw.Dispose();

Deserialize an XML file to an object (assuming that you have the classes created):

                Object obj = new object();


                XmlSerializer xs = new XmlSerializer(objectDestination.GetType());
                FileStream fs = new FileStream(pathToXML, FileMode.Open);
                XmlReader xr = new XmlTextReader(fs);
             
                obj = xs.Deserialize(xr);
                fs.Close();

Here we have a method that takes the XML string as paramater returns an object of type T:

public static T DeserializeXMLToObject(string objectAsXml)
{
XmlSerializer xs = new XmlSerializer(typeof(T)); MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(objectAsXml)); XmlReader xr = new XmlTextReader(ms); T obj = (T)xs.Deserialize(xr); return obj;
}

Thursday, January 10, 2013

Default values for date parameters in SSRS

I will create a report that will have 3 parameters:

Interval: type: int with the following available values:

StartDate: type: DateTime; this will have different default values depending on the value of the Interval parameter.

The default values for the StartDate are:

For this week (first day of current week, Monday)
DateAdd("d", 1 - DatePart(DateInterval.WeekDay, Today(),FirstDayOfWeek.Monday), Today())

For last week (first day of last week, Monday)

DateAdd(DateInterval.Day, -6,DateAdd(DateInterval.Day, 1-Weekday(today),Today))


For current month
DateSerial(Year(DateTime.Now),Month(DateTime.Now),1)

For last month
DateSerial(Year(DateTime.Now),Month(DateTime.Now)-1,1)

The DateSerial function automatically generates the correct date also in January. If the value for the month = 0 then it sets month 12 of the previous year (year is also changed).

For last quarter: 
DateAdd("q",DateDiff("q","1/1/1900",today)-1,"1/1/1900")

For last year
DateSerial(Year(DateTime.Now)-1,1,1)


We set the default values using the switch function:


switch(Parameters!Interval.Value=1,DateAdd("d", 1 - DatePart(DateInterval.WeekDay, Today(),FirstDayOfWeek.Monday), Today())
Parameters!Interval.Value=2,DateAdd(DateInterval.Day, -6,DateAdd(DateInterval.Day, 1-Weekday(today),Today)),
Parameters!Interval.Value=3,DateSerial(Year(DateTime.Now),Month(DateTime.Now),1),
Parameters!Interval.Value=4,DateSerial(Year(DateTime.Now),Month(DateTime.Now)-1,1),
Parameters!Interval.Value=5,DateAdd("q",DateDiff("q","1/1/1900",today)-1,"1/1/1900"),
Parameters!Interval.Value=6,DateSerial(Year(DateTime.Now)-1,1,1)
)



EndDate: type: DateTime; this will have different default values depending on the value of the Interval parameter.


For this week (last day of current week, Sunday)
DateAdd("d" ,7- DatePart(DateInterval.WeekDay,Today(),FirstDayOfWeek.Monday),Today())

For last week (last day of last week, Sunday)
DateAdd(DateInterval.Day, -0,DateAdd(DateInterval.Day, 1-Weekday(today),Today))

For current month
DateSerial(Year(DateTime.Now), Month(DateTime.Now)+1,0)

For last month
DateSerial(Year(DateTime.Now), Month(DateTime.Now),0)

If the day = 0, the date will become the last day of the previous month.


For last quarter: 
DateAdd("s",-1,DateAdd("q",DateDiff("q","1/1/1900",Today),"1/1/1900"))

For last year
DateSerial(Year(DateTime.Now)-1,12,31)


Again we set the default values using the switch function:


switch(Parameters!Interval.Value=1,DateAdd("d" ,7- DatePart(DateInterval.WeekDay,Today(),FirstDayOfWeek.Monday),Today()),
Parameters!Interval.Value=2,DateAdd(DateInterval.Day, -6,DateAdd(DateInterval.Day, 1-Weekday(today),Today)),
Parameters!Interval.Value=3,DateSerial(Year(DateTime.Now), Month(DateTime.Now)+1,0),
Parameters!Interval.Value=4,DateSerial(Year(DateTime.Now), Month(DateTime.Now),0)
Parameters!Interval.Value=5,DateAdd("s",-1,DateAdd("q",DateDiff("q","1/1/1900",Today),"1/1/1900"))
Parameters!Interval.Value=6,DateSerial(Year(DateTime.Now)-1,12,31)
)




Monday, January 7, 2013

Using ActionFilters to prevent unauthorized access

In this post I am going to create an ActionFilter for my ASP.NET MVC website that checks if the user is authenticated before accessing a page.

First I have to create a class that will inherit from ActionFilterAttribute:
public class MyAuthClass: ActionFilterAttribute

Inside the class we override the method OnActionExecuting (is called before an action of a controller is executed):

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string controllerName = filterContext.Controller.GetType().Name;

            //the only controller that doesn't need authentication is the Login Controller
            if (!controllerName.Equals("LoginController"))
            {
             

                bool IsAuth = false;

                IsAuth = true; //Normally here you must implement some logic that checks if the login succeeded or not.

                if (!IsAuth) //not authenticated, send it back to the login page
                {
                    RouteValueDictionary redirectDict = new RouteValueDictionary();
                    redirectDict.Add("action", "Login");
                    redirectDict.Add("controller", "Login");

                    filterContext.Result = new RedirectToRouteResult(redirectDict);
                }
            }
           
        }

In order for the ActionFilter to work we need to write above the Controller declaration the following:


[MyProject.ActionFilters.MyAuthClass] 
 public class BaseController : Controller
    {
     //some code goes here;
      }

 

For a better understanding of Action Filters in MVC follow this tutorial: http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

Tuesday, December 18, 2012

DateTime EditorTemplates and DefaultModelBinder

In order to use EditorTemplates with ASP.NET MVC 3 and Razor you need to do the following:
1. Create a folder named EditorTemplates in Views\Shared.
2. Add a new MVC3 View Page (Razor)

Inside the cshtml file write the code for the template:


@model System.DateTime?
@* <div class="editor-label">
    @Html.Label("")
</div>*@
<div class="editor-field">
    @Html.TextBox("",
    String.Format(@"{0:dd.MM.yyyy}",
        (Model.HasValue && Model.Value > new DateTime(1,1,1) )? Model.Value.Date : DateTime.Today),
                    new { @class = "editor-field" }
                 )
</div>

<script type="text/javascript">
    $(document).ready(function () {
        $("#@ViewData.ModelMetadata.PropertyName").datepicker({
            changeMonth: true,
            changeYear: true,
            dateFormat: "dd.mm.yy",
            firstDay: 1 // starts on monday
        });
    });
</script>


In my model I had the DateTime fields as not nullable and therefore I always seemed to receive the date 01/01/01. If my model had no value defined, the textbox would show the date 01/01/01. To overcome this I added the condition that Model.Value > new DateTime(1,1,1).


The problem with the code above was that it returned an invalid date if the computer that was accessing the site had a different format of the date (eg.: MM/dd/yyyy). The "cure" for this was to override the BindProperty in a class that inherited from DefaultModelBinder:



public class DateFixModelBinder :  DefaultModelBinder
    {

        protected override void BindProperty(ControllerContext controllerContext,
            ModelBindingContext bindingContext,
            System.ComponentModel.PropertyDescriptor propertyDescriptor)
        {

            if (propertyDescriptor.PropertyType == typeof(DateTime))
            {
                var model = bindingContext.Model;
                PropertyInfo property = model.GetType().GetProperty(propertyDescriptor.Name);
                DateTime date = DateTime.Today.Date;

                try
                {

                    var value = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
                    if (value != null)
                    {
                        date = DateTime.ParseExact(value.AttemptedValue, "dd.MM.yyyy", null);
                        property.SetValue(model, date, null);

                    }
                }
                catch (Exception)
                {

                    property.SetValue(model, date, null);
                }

            }
            else
            {
                base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
            }


        }


Also in Global.asax, in Application_Start,  you need to write the following code:

 ModelBinders.Binders.DefaultBinder = new DateFixModelBinder();

Saturday, September 29, 2012

Dynamically add HTML markup to ASP.NET page

Sometimes you just might need to add dynamic HTML markup to your ASP.NET pages. I had to do the same thing and here I will show you how I did it.

First I created a div in my ASP.NET page like this:

<div id="myDiv" runat="server"></div>
The important things to note here are:
1. We need a name for the div, in this case "myDiv".
2. The attribute runat = "server". This attribute signifies that the control is a server control and the enclosed controls can be accessed by server scripts. If this attribute was missing, the server would have treated the line of code as a simple line of text.

Next thing to do we will write code in C# in the page load event. The full code looks like this:


protected void Page_Load(object sender, EventArgs e)
        {

            LiteralControl myList = new LiteralControl();
            System.Web.UI.Control myDiv = (System.Web.UI.Control)this.Page.FindControl("myDiv");

            StringBuilder sb = new StringBuilder(); //needs using System.Text on top of the page
            sb.Append("<ul>"); //the start of the list
            for (int i = 0; i < 4; i++)
            {
                sb.Append("<li>Item ");
                sb.Append(i.ToString());
                sb.Append("</li>");

            }

            sb.Append("</ul>"); //the end of the list

            myList.Text = sb.ToString();

            this.myDiv.Controls.Add(myList);

        }

So here we instantiate a LiteralControl whose text property will take the new HTML markup that we need on the page.

Then we search the page with the FindControl method of the Page that takes as parameter the name of the div where the new HTML will reside.

I created the HTML markup using a StringBuilder object. This class is very useful when working with strings because of the better memory management it has over the String class when concatenating.

The rest of the code is pretty clear.

Wednesday, September 26, 2012

Alternating color for rows or columns in SSRS

I needed to display some reports with alternating colors for columns today. The report was a matrix report that had a column group that showed the months of the year.

After selecting the column go to properties and click on Fill -> Background color -> Expression



In the expression box type the following:

=iif(Fields!MonthNumber.Value mod 2,"Transparent","LightGrey")

 The same thing can be achieved for the rows. Instead of selecting the column, select the row of the table and follow the same steps.

Hope it will be usefull!