mercredi 6 mai 2015

Remote validation is not working

When I entered value for email in textbox it didn't fire VerifyUserEmail method. Below is my code. Where is my mistake?

View

<div class="form-group">
    @Html.LabelFor(model => model.User_Email, new { @class = "control-label col-lg-2" })
        <div class="col-lg-4">
            @Html.EditorFor(model => model.User_Email)
            @Html.ValidationMessageFor(model => model.User_Email)
        </div>
</div>

Model

[DisplayName("Email")]       
[Remote("VerifyUserEmail", "User", ErrorMessage = "Email already exists!")]
public string User_Email { get; set; }

Controller

    public JsonResult VerifyUserEmail(string User_Email)
    {
        try
        {
            using (RKDYMEntities objConnection = new RKDYMEntities())
            {
                ObjectParameter objIErrorCode = new ObjectParameter("ErrorCode", typeof(Int32));
                ObjectParameter objBFlag = new ObjectParameter("bFlg", typeof(bool));
                objConnection.Check_User_Exists(User_Email, objBFlag, objIErrorCode);

                if (Convert.ToBoolean(objBFlag.Value) != true)
                {
                    return Json(false, JsonRequestBehavior.AllowGet);
                }
                else
                {
                    return Json(true, JsonRequestBehavior.AllowGet);
                }


            }
        }
        catch (Exception Ex)
        {
            return Json(false, JsonRequestBehavior.AllowGet);
        }
    }

I have also added <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> in web.config.

Below is generated html code:

 <div class="form-group">
    <label class="control-label col-lg-2" for="User_Email">Email</label>
        <div class="col-lg-4">
            <input class="text-box single-line" data-val="true" data-val-length="The field Email must be a string with a maximum length of 200." data-val-length-max="200" data-val-remote="Email already exists!" data-val-remote-additionalfields="*.User_Email" data-val-remote-url="/User/VerifyUserEmail" id="User_Email" name="User_Email" type="text" value="" />
            <span class="field-validation-valid" data-valmsg-for="User_Email" data-valmsg-replace="true"></span>
       </div>
 </div>

Send double value to MVC controller as a string

I've got an action in my controller

    [HttpGet]
    [Route("classificators/{type}/{criteria}/{predicate?}")]
    public ActionResult Classificators(string type, string criteria, string predicate)
    {
        try
        {
            //Lot's of cool code here!          

            return Json(new { Data = "Cool data!" }, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            return Json(new
            {
                state = "error",
                message = ExceptionReport(ex)
            }, JsonRequestBehavior.AllowGet);
        }
    }

And sending request to it like so..

/classificators/MAIN/CODE/50.1

Where: type - MAIN criteria - CODE predicate - 50.1

But action treats parametr 50.1 like double value so I've got an error. How to specify action to treat this value like a string

Image displaying error from database

After the recent changes in my application still i get this issue while displaying the image using the relative path in the database. Error: 404 NOT FOUND http://localhost:1256/Empdet/%22/Photos/jobs.jpg%22

Screenshot

Controller.js:

 $scope.UploadFile = function () {
    console.log('UploadFile');
    console.log($scope.Empdet.PhotoFile);
    var file = $scope.Empdet.PhotoFile;
    console.log('file is ' + JSON.stringify(file));
    var uploadUrl = "../Photos";
    console.log('before file upload');
    EmployeeFactory.UploadFile(file, uploadUrl).success(function (response)  {
        $scope.Empdet.PhotoText = response;
        console.log('$scope.Empdet.PhotoText');
        console.log(response);
    }).error(function () {
        console.log('error');
    });
    console.log('after file upload');
};

service.js:

service.UploadFile = function (file, uploadUrl) {
    var fd = new FormData();
    fd.append('file', file);
    return $http.post('/Empdet/UploadFile', fd, {
        transformRequest: angular.identity,
        headers: { 'Content-Type': undefined }
    });
}

EmpdetController.cs:

[HttpPost]
    public ActionResult UploadFile()
    {
        var file = Request.Files[0];
        var path = Path.Combine(Server.MapPath("~/Photos/"), file.FileName);
        file.SaveAs(path);

        // prepare a relative path to be stored in the database and used to display later on.
        var filename = Url.Content("~/Photos/" + file.FileName);
        // save to db
        return Json(filename.ToString(), JsonRequestBehavior.AllowGet);

    }

How to disable radio button overwrite?

I have second thing on my page: In array (Completed is bool):

@Html.EditorFor(m => Model.Options[i].Completed)

As html this looks like

<td>
    Yes 
    <div id="Options_0__Completed-styler" class="jq-radio" unselectable="on" style="-webkit-user-select: none; display: inline-block; position: relative;">
        <input id="Options_0__Completed" name="Options[0].Completed" type="radio" value="True" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">
        <div class="jq-radio__div"></div>
    </div>
    No
    <div id="Options_0__Completed-styler" class="jq-radio checked" unselectable="on" style="-webkit-user-select: none; display: inline-block; position: relative;">
        <input checked="checked" id="Options_0__Completed" name="Options[0].Completed" type="radio" value="False" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">
        <div class="jq-radio__div"></div>
    </div>
</td>

My issue is that potentialy, because of jq-radio (comes from jquery.formstyler.js) I can't do any change for radio buttons.

For example:

    for (var i = 0; i < value; i++) {
        var test = $('input[name="Options[' + i + '].Completed"]').filter('[value=False]');
        test.attr('disabled', true);
    }

If I look on html, then I will see that input with value False is disabled, BUT visually, nothing changes for be.

How can I fix this kind of issue?

Inherited RoutePrefixAttribute in ASP.NET MVC

Currently, my ASP.NET MVC website uses RouteConfig.RegisterRoutes to map routes. I would like to convert this to the new Attribute routing system, but I am missing one small thing there.

The website is multi-language, so every URL needs to be prefixed with a two-letter ISO language code. In the current implementation, the website uses a custom RouteHandler to handle the culture part of all routes. After registering all routes, a loop adds the custom handler and culture constraints to every route.

See below the current implementation:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.RouteExistingFiles = true; 

        // various calls to routes.MapRoute()

        foreach (Route r in routes)
        {
            if (!(r.RouteHandler is SingleCultureMvcRouteHandler))
            {
                r.RouteHandler = new MultiCultureMvcRouteHandler();
                r.Url = "{culture}/" + r.Url;

                // Add the default language
                if (r.Defaults == null)
                    r.Defaults = new RouteValueDictionary();
                r.Defaults.Add("culture", Culture.nl.ToString());

                // Add language constraints
                if (r.Constraints == null)
                    r.Constraints = new RouteValueDictionary();
                r.Constraints.Add("culture", new CultureConstraint(Culture.nl.ToString(), Culture.de.ToString(), Culture.en.ToString(), Culture.fr.ToString()));
            }
        }
    }
}

Culture enum:

public enum Culture
{
    nl = 1,
    en = 2,
    de = 3,
    fr = 4
}

Custom routehandler:

public class SingleCultureMvcRouteHandler : MvcRouteHandler { }

public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var culture = requestContext.RouteData.Values["culture"].ToString();
        var ci = new CultureInfo(culture);
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL");

        return base.GetHttpHandler(requestContext);
    }
}

Culture constraints

public class CultureConstraint : IRouteConstraint
{
    private string[] _values;
    public CultureConstraint(params string[] values)
    {
        this._values = values;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        string value = values[parameterName].ToString();
        return _values.Contains(value);
    }
}

In order to convert this to the new AttributeRouting, I just thought I'd add a RoutePrefix attribute to my base controller, which would handle the culture part. BUT it seems inheritance of route attributes is not supported...

The release notes of ASP.NET MVC 5.2 state that inherited route attributes are supported in that version by implementing a custom RouteAttribute and DirectRouteProvider. This is however for the RouteAttribute, not for the RoutePrefixAttribute.

What I have tried:

I've tried to create my own InheritedRoutePrefixAttribute by inheriting from the RoutePrefixAttribute, but then in order to actually support the inherited route, I still need to create a InheritedDirectRouteProvider and override the GetControllerRouteFactories() method, which returns a collection of IDirectRouteFactory.
So in order to do that, my InheritedRoutePrefixAttribute needs to implement the IDirectRouteFactory interface, but what to do in the CreateRoute() method?

My code so far:

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class InheritedRoutePrefixAttribute : RoutePrefixAttribute, IDirectRouteFactory
{
    public RouteEntry CreateRoute(DirectRouteFactoryContext context)
    {
        // ...
    }
}

Custom route provider

// Custom direct route provider which supports attribute route inheritance.
public class InheritedDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> GetControllerRouteFactories(ControllerDescriptor controllerDescriptor)
    {
        return controllerDescriptor.GetCustomAttributes(typeof(InheritedRoutePrefixAttribute), inherit: true).Cast<IDirectRouteFactory>().ToArray();
    }
}

ASP.NET MVC customError page doesn't get displayed for some of the 400 errors

I'm having quite an interesting issue with the custom error pages management for a new ASP.NET MVC application.

This issue is like this:
- if I'm calling an URL (doesn't matter which) with a "bad" argument at the end of URL, like ..../c<, the application is displaying the correct server error page as instructed in the web.config;
- if I'm changing the URL to a more nasty one, like .../<c (to look more like an HTML tag, there is no more server error page displayed in the browser and instead of that, I'm getting a plain YSOD with a message like An exception occurred while processing your request. Additionally, another exception occurred while executing the custom error page for the first exception. The request has been terminated.

According to ELMAH, both requests ended with a 400 status code and the message being:
- for the first one: System.Web.HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (<). at System.Web.HttpRequest.ValidateInputIfRequiredByConfig() at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)
- for the second one: System.Web.HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (<). at System.Web.HttpRequest.ValidateInputIfRequiredByConfig() at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)

So, both errors are the same, the status code is the same, but for one of the errors, the custom error page is not getting displayed. I've also went to global.asax in debug mode and checked the Server.GetLastError() in protected void Application_Error(object sender, EventArgs e) and again, both errors were the same, nothing is different.

In web.config, this is how my <customErrors> tag looks like:

<customErrors mode="On" defaultRedirect="/ServerError.aspx" redirectMode="ResponseRewrite"> <error statusCode="500" redirect="/ServerError.aspx" /> <error statusCode="404" redirect="/PageNotFound.aspx" /> </customErrors>

Can please someone tell me why the behavior is different in these two cases?

Thank you very much for your time.

Which version should i start for MVC

I am new in MVC Framework, I have just developed application in web form application till now Please suggest me, may i start MV3 or MVC 5 ?