Showing posts with label ASP.NET MVC. Show all posts
Showing posts with label ASP.NET MVC. Show all posts

Monday, July 21, 2014

Could not load file or assembly 'WebGrease, Version=1.5.1.25624, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies

I was working on a MVC 5 project in Visual Studio 2013, and I was getting the error in the title everytime I was trying to run the project. We were using Visual SVN for the versioning and I was the only one in my team that had this problem.

The only thing that worked for me was this:
  1. Uninstall Microsoft.AspNet.Web.Optimization
  2. In Nuget command prompt run: install-package Microsoft.AspNet.Web.Optimization -Version 1.0.0

This will install an older version of Web.Optimization. The project was initially referencing version 1.1.0. The problem is not with WebGrease, but with the System.Web.Optimization.dll that is referencing an old, inexisting version of WebGrease.

When I ran the project, it worked, but I wanted to use the same package version as the rest of team. So, I tried to update but... the error returned...

After this, I deleted the project (again) and took it back from the SVN. To my surprize, it started to work... The thing is that I had deleted the project completely and took it from the SVN several times before this. I even took the dlls from a colleague because I thought that maybe I'm getting corrupted files from NuGet, but to no avail.

Strange...

Friday, June 6, 2014

Posting a form to get a file in return

I was working on an ASP.NET MVC application that, at some point, had to display the PDF version of an invoice. The file was stored on 3rd party's server and the only way you could get it was by posting a form. The form had to have an action (link) set and 2 inputs, one for the password and one for the username.

In order to achieve this, there are 2 possible solutions, but (in this case) only one (Solution 2) is the right solution.

So let's begin with the first solution.

Solution 1

First we write the html for the form:

    <form id="frmInvoice" method="post" target="_blank" >

        <input type="hidden" name="user" value="@Model.UserName" id="user" />

        <input type="hidden" name="pwd" value="@Model.Password" id="pwd" />

    </form>

Not so much to say here, just that the inputs for password and username are all hidden, meaning they will not appear in the web page.

Somewhere outside the form we create a button that will submit the form through a javascript function. We could have defined the button inside the form, but in this application it was not the case.

<input type="button" value="pdf" id="@Model.InvoiceNumber" onclick="postInvoiceForm(@Model.InvoiceNumber, '@Model.ActionLink');"  />


This button will call the javascript function below:

 function postInvoiceForm(invoiceNbr, actionLink) {

        var form = document.getElementById('frmInvoice');

        form.setAttribute('action', actionLink + invoiceNbr);

        form.submit();

    }


The 'action'  is the link where the form has to be posted, something like http://www.siteWithPdfs.com/pdfid. In order for the javascript function to work I had to put the value inside single quotes.

Problem

The problem with this approach is that the username and password are visible in the page if you look at the source. This is the reason I had to go with the second option.You could use this solution if you did not have any user and password, since it would be the fastest to implement.



Solution 2

Use WebRequest instead.

In the view change the button with:

<a href="@Url.Action("GetInvoicePDF", "MyController", new { invoiceNumber = Model.InvoiceNumber })" target = "_blank">

          <img src="@Url.Content("~/Content/images/filetype_pdf.png")" alt="pdf" />

 </a>

The target = _blank is set so that I get the pdf in a new tab (or window) and I don't loose the page I was coming from.

In the MyController controller, create the method GetInvoicePDF:

public ActionResult GetInvoicePDF (string invoiceNumber)

{

   WebRequest request = WebRequest.Create("www.siteWithPdfs.com");

   request.Method = "POST";

   request.ContentType = "application/x-www-form-urlencoded";

            

   Encoding iso8859_1 = Encoding.GetEncoding("iso-8859-1");

   StreamWriter sw = new StreamWriter(request.GetRequestStream(), iso8859_1);

   sw.Write("User=");

   sw.Write(HttpUtility.UrlEncode(Model.UserName, iso8859_1));

   sw.Write("Pwd=");

   sw.Write(HttpUtility.UrlEncode(Model.Password, iso8859_1));

   sw.Close();



Stream fs = request .GetResponse().GetResponseStream();

var fsResult = new FileStreamResult(fs, "application/pdf");

return fsResult;

}


The method creates a WebRequest object that will be used to post the form. The encoding was used only because I had to prepare for nordic characters.





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" })

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();