Wednesday, October 16, 2013

IIS error - Request entity too large


I had been working on a WCF web service lately that received the contents of a file as byte array and saved it in a database.

When calling the web-service I received the error "Request entity too large." Although the file was less than 200kb it was not able to process it.

The solution was to put the following tags inside the <system.serviceModel> tag in web.config.

<system.serviceModel>
                <bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="2097152"></binding>
</basicHttpBinding>
</bindings>
  </system.serviceModel>

Friday, September 6, 2013

Make field readonly with Javascript

In this post I will show an example of making a textbox that is bound to a model, read-only/editable when a user checks/unchecks a checkbox.

Our controls will start in the following state: the checkbox (chkIsReadOnly) is unchecked and the textbox is editable.

When the user clicks on the checkbox the following javascript function will be launched:

function changeState() {
            var checkValue = document.getElementById("chkIsReadOnly").checked;
            var userName= document.getElementById("userName");

            if (!checkValue) {
               //the field becomes readonly since the checkbox is checked
                userName.readOnly = false;
                userName.removeAttribute('readonly');
                userName.removeAttribute('disabled');
            }
            else {

                userName.readOnly = true;
                userName.setAttribute('readonly', true);
                userName.setAttribute('disabled', true);
                userName.value = '';
            }

        };

The checkbox is defined like this:
<input
                            type="checkbox"
                            name="chkIsReadOnly"
                            id="chkIsReadOnly"
                            onclick="changeState()"
  />

In order for the javascript function to work we must use the HTML helper TextBoxFor instead of EditorFor

@Html.TextBoxFor(model => model.userName, new { disabled = "disabled", @readonly = "readonly" })

Friday, August 30, 2013

Default GETDATE() contraint for column and LINQ in Entity Framework 5.0

If we have a datetime column that we want to set the default to the current date and time we can use

alter table MyTable add constraint DefGetDate DEFAULT GETDATE() FOR myColumn


In edmx, select the column from the entity and set the StoreGeneratedPatern to Computed or Identity.

The available values for StoreGeneratedPatern are:


  • None A value indicating that it is not a server generated property. This is the default value.
  • Identity A value is generated on insert and remains unchanged on update.
  • Computed A value is generated on both insert and update.

The MSDN page regarding this is http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.storegeneratedpattern.aspx

Tuesday, August 27, 2013

Render file from ReportViewer connected to Reporting Services

In this post I will show how you can use a report viewer control to connect to a Reporting Services server and call the Render function on the ReportViewer.
This is useful when we don't want to show the control, but we need to get the rendered report in different formats.

Step 1: download the Report viewer runtime from here.

Step 2: Install the runtime.

Step 3: Add the reference to your project. The dll should be in \Program Files (x86)\Microsoft Visual Studio 11.0\ReportViewer\Microsoft.ReportViewer.WinForms.dll

First we create a method that will return the report from the report viewer as an array of bytes.

public byte[] RenderFromServer()
{
ReportViewer rv = new ReportViewer();

// Set the processing mode for the ReportViewer to Remote
rv.ProcessingMode = ProcessingMode.Remote;

rv.ServerReport.ReportServerUrl = new Uri("Http://mypc/ReportServer);
rv.ServerReport.DisplayName = "New report.pdf";
rv.ServerReport.ReportPath = "/Reports/MyReport";

//set credentials
ReportServerCredentials rsCredentials = rv.ServerReport.ReportServerCredentials;

NetworkCredential nc = new NetworkCredential();
nc.Domain = "myDomain"; //can also be the computer name for local access
nc.UserName = "myUser";
nc.Password = "12333";

rsCredentials.NetworkCredentials = nc;

//set parameters
List<ReportParameter> paramLst = new List<ReportParameter>();
ReportParameter rp = new ReportParameter(ParamName, ParamValue);
paramLst.Add(rp);
                        rv.ServerReport.SetParameters(paramLst);

//get the bytes from the report viewer
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;

byte[] bytes = rv.ServerReport.Render
("PDF", null, out mimeType, out encoding, out extension, out streamids, out warnings);

rv.Dispose(); //very important for memory management!!
return bytes;
}


Notice that I called the Render function with the "PDF" paramater. The full list can be found at http://msdn.microsoft.com/en-us/library/ms154606.aspx.

The possible values are:

  • PDF
  • CSV
  • IMAGE
  • PDF
  • EXCEL
  • WORD
  • HTML 4.0
  • MHTML
When exporting to MHTML and you need to embed the report in another html document, or the body of an email, you have to specify the DeviceInfo details:

<DeviceInfo>
   <HTMLFragment>True</HTMLFragment>
</DeviceInfo>

As stated in MSDN, "When a report is rendered as an HTML fragment, the content of the report is contained within a TABLE element without the use of an HTML or BODY element. You can use the HTML fragment to incorporate the report into an existing HTML document."

Link: http://technet.microsoft.com/en-us/library/ms155397.aspx

Then we can write the bytes to a file:

byte[] bytes = RenderFromServer();
File.WriteAllBytes("C:\\MyReport.pdf", bytes);

Or, make a memory stream from them:

byte[] bytes = RenderFromServer();
MemoryStream ms = new MemoryStream(bytes);
ms.Seek(0, SeekOrigin.Begin);

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