Archive

Posts Tagged ‘ASP.net’

HowTo: change color of validation messages in ASP.net MVC

If you need to customize the colors (or do more restyling) of validation messages in ASP.net MVC, the following snippet from a discussion on ASP.net forums should be useful:

Add to Content/Site.css:

/* styles for validation helpers */

.field-validation-error {
    color: #b94a48;
}

.field-validation-valid {
    display: none;
}

input.input-validation-error {
    border: 1px solid #b94a48;
}

select.input-validation-error {
    border: 1px solid #b94a48;
}

input[type="checkbox"].input-validation-error {
    border: 0 none;
}

.validation-summary-errors {
    color: #b94a48;
}

.validation-summary-valid {
    display: none;
}

Other useful replies from there:

@Html.ValidationSummary(true,"",new {@style= "color: red"})

The method for MVC 5 + Bootstrap is:
@Html.ValidationSummary(true, "", new { @class = "text-danger" })

Advertisements

HowTo: include MVC model property Display name in Required validation message

Just came across this validation error display in an MVC app I’ve recently started maintaining. The required input field validation seemed to not be localized, resulting in a mixed English and Greek (from the field’s Display name) message:

image

Looking at the MVC model I noticed they were using [Required] attributes for the userName and password properties, together with [Display(Name = "…")] for the displayed property title

public class LoginModel
  {
     [Required]
     [Display(Name = "Όνομα Χρήστη")]
     public string userName { get; set; }

     [Required]
     [DataType(DataType.Password)]
     [Display(Name = "Κωδικός")]
     public string password { get; set; }

     //…

That was changed to:

public class LoginModel
  {
     [Required(ErrorMessage = "Το {0} είναι απαραίτητο.")]
     [Display(Name = "Όνομα Χρήστη")]
     public string userName { get; set; }

     [Required(ErrorMessage = "Το {0} είναι απαραίτητο.")]
     [DataType(DataType.Password)]
     [Display(Name = "Κωδικός")]
     public string password { get; set; }

resulting in a fully localized validation error message with the respective property’s Display name auto-inserted in the validation ErrorMessage, thanks to the {0} used in the message string:

image

Note there’s also the lazy route like in this property:

[Display(Name = "Περίοδος Εγγύησης(Έτη):")]
[Required(ErrorMessage = "Απαραίτητο πεδίο")]
public int warrantyPeriod { get; set; }

where you just say something like “Required field” in the localized error message. This however will work only when you always show the error message next to the input field that fails to pass validation.

If you want to also show a validation summary say at the beginning and/or the end of the page (depending on where your submit button is), you’ll end up with an error summary that may just contain multiple entries of “Required field” text without any indication on what field it was (which would be practically useless that is).

Note that sometimes due to lack of space in a webpage (say if you have lots of input fields in a grid) you can only show say red “*” near input fields that have validation errors and explain them more in the tooltips and in an error summary control.

Even better you can use resource strings to avoid error message string duplication. That approach, though a bit more verbose as implemented in ASP.net means easier centralized maintenance and localization from a per locale/language resource file and less typos or slightly different error messages for the same thing. See example and related screenshots at https://stackoverflow.com/a/22849638

Fix: jQuery’s jqGrid search UI custom styling

Lately, I’ve got the task of maintaining/extending an ASP.net MVC web application that is using jQuery’s jqGrid for data grids on its UI. First thing I noticed was how confusing the search UI on the grid’s header was:

image

Those symbols on the left-side of each column’s searchbox are for the type of search (e.g. contains, doesn’t contain, equals, starts with, doesn’t start with, ends with, doesn’t end with).

Bit too many options and using programming-related symbols that probably intimidate several users in my opinion:

image

But the worse is the “x” button (that clears the searchbox) on the right of each searchbox, that combined with the search-type symbols makes the whole search bar look like some strange mathematical expression.

So using the browser dev tools (F12) and some CSS rules I quickly restyled that search bar to make it more appealing UI/UX wise:

image

Added a border around the “x” button that clears the searchbox and offseted using a negative margin so that the searchbox and it fuse together visually on their sides. Also made the search-type symbol (that opens the search-type selection popup when clicked) of lighter color. It may look a bit-like some disabled thing like that, but at least it should confuse average users less with its use of technical symbols like that.

Just need to add the rules above at the ASP.net MVC app’s Site.css (probably to be found at the Content subfolder of the webapp) and remember to press F5/Refresh in one’s browser in case the old styling still appears due to caching.

Update #1:

I noticed on older versions of Windows (other than Windows 10 that is) that bevels were showing at the text inputs, leading to this ugly effect:

image

So I had to add some more rules to remove the bevel borders and use a consistent border color.

Removing the bevels seemed to also remove the inner padding of the text inputs, so added a padding of 2px and some box-sizing rules to make sure the padding doesn’t affect the input’s size.

/* OS-independent styling for input and textarea borders */
textarea,
input[type="text"],
input[type="password"] {
    border-style: solid;
    border-width: 1px;
    border-color: gray;
    padding: 2px;
    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
    -moz-box-sizing: border-box; /* Firefox, other Gecko */
    box-sizing: border-box; /* Opera/IE 8+ */
}

Update #2:

After recently updating some jQuery related NuGet packages in that ASP.net project, I noticed the [x] button was showing a bit higher up at the bottom compared to the search box. The fix to that was to add padding-bottom: 1px; at the CSS declaration for clearsearchclass in Content/Site.css

a.clearsearchclass {
    border-width: 1px;
    border-style: solid;
    /* border-left-style: none; */
    margin-left: -3px;
    padding-bottom: 1px; /* seems to be needed with newer jQuery.UI */
    background: whitesmoke;
    border-color: gray;
}

Categories: Posts Tags: , , , , , , , , ,

Workarround: IE11 changing download file extension to .zip

At ClipFlair Gallery, apart from opening a ClipFlair activity in ClipFlair Studio, downloading of an activity (.clipflair) file is also supported.

However, because the component serialization file format of ClipFlair Studio is XML plus media assets packed in .zip archive (with nesting allowed, where components and whole activities can be placed in other activities), Internet Explorer 11 (and probably other browsers too) was downloading .clipflair files as .zip (changing their file extension).

At first, I thought that occured because I was using MIME type “application/zip” at the IIS web server/site settings for that file extension. So then I tried to change it to “application/octet-stream” hoping that one would be treated as an “opaque” data stream.

However, eventually I ended up setting a custom MIME type “application/clipflair” for the file extension “.clipflair”, because even with “application/octet-stream” (as with the “application/zip” that I had before), IE11 was still saving the .clipflair file as .zip (obviously detecting the zip content in the download stream).

<?xml version=”1.0″?>
<configuration>

<system.webServer>

<directoryBrowse enabled=”true” showFlags=”Size, Extension”/>

<defaultDocument>
<files>
<clear/>
<add value=”index.html”/>
<add value=”Default.aspx”/>
<add value=”Default.html”/>
</files>
</defaultDocument>

<caching>
<profiles>
<add extension=”.log”
policy=”CacheUntilChange”
kernelCachePolicy=”CacheUntilChange”/>
</profiles>
</caching>

<staticContent>
<mimeMap fileExtension=”.log” mimeType=”text/plain”/>
<mimeMap fileExtension=”.clipflair” mimeType=”application/clipflair”/>
<mimeMap fileExtension=”.dzi” mimeType=”text/xml”/>
<mimeMap fileExtension=”.dzc” mimeType=”text/xml”/>
<mimeMap fileExtension=”.cxml” mimeType=”text/xml”/>
</staticContent>

</system.webServer>

<system.web>
<compilation debug=”true” targetFramework=”4.0.3″/>
</system.web>

</configuration>

HowTo: Use WordPress Permalinks on IIS

at http://zachis.it/blog/7-dangers-of-using-windows-server-on-a-wordpress-installation/

the thing that guy says about Permalinks isn’t accurate at all (not that the other things that he says are any accurate that is). WordPress Codex have documentation on how to configure URL rewriting in web.config that is necessery for Permalinks to work in IIS.

e.g. at http://ClipFlair.net, if you press the "about" icon you’re taken to a WordPress site that runs on IIS and uses permalinks fine and hides the index.php too from the URL

in its web.config I have the following:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>

        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" prefixLanguageFilePath="" path="/index.php?error=404" responseMode="ExecuteURL" />
        </httpErrors>

        <!– Needed for WordPress Permalinks –>
        <rewrite>
            <rules>

                <rule name="Main Rule" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <!– <action type="Rewrite" url="index.php/{R:0}" /> –>
                    <action type="Rewrite" url="index.php" />
                </rule>

            </rules>
        </rewrite>

        <defaultDocument>
            <files>
                <clear />
                <add value="index.html" />
                <add value="index.php" />
                <add value="default.aspx" />
            </files>
        </defaultDocument>

    </system.webServer>
</configuration>

Gotcha: use server-side comment, not HTML comment in ASP.net

I try to remember to use <%– and –%> instead of <!– and –> for comments in server-side web pages, to avoid having implementation details (for security reasons that is) in the output HTML and to keep the download size smaller / have the pages load faster.

What came to me though the other day while making some metadata editing pages for ClipFlair Gallery, was that if you don’t use server-side comments and use classic HTML comments in server-side pages, the code inside the HTML comments is executed at the server side and its output is placed in HTML comments at the web page the client browser downloads.

So this can potentially lead to a very big download and to increased time to generate the page at the sever-side if you accidentally comment out some code block you were using for testing and don’t use server-side comments, but use HTML comments instead to comment it out.

What got me into suspission was the syntax highlighting of Visual Studio 2010. Note below that <%@ Register isn’t highlighted green (as it would be in a server-side comment).

<%@ Page Language="C#" 
         AutoEventWireup="true"
         Title="ClipFlair Activity Gallery"
%>

<!-- THIS IS A BAD USE OF HTML COMMENT MARKER, USE SERVER-SIDE COMMENT INSTEAD

<%@ Register Assembly="CustomXml" Namespace="PAB.WebControls" TagPrefix="cc2" %>

<cc2:CustomXml 
  DocumentUrl="http://gallery.clipflair.net/activity/all.xml"
  XslUrl="http://gallery.clipflair.net/activity/activity.xsl"
  runat="server"
  />

-->

...

Probably JavaEE’s JSP behaves similarly (uses the same symbols for server-side comments), but haven’t tested it.

Categories: Posts Tags: , , , , ,

HowTo: Bind ASP.net control to list of files or folders

At ClipFlair Gallery metadata input pages for Activities and Clips I had to bind an ASP.net control to a list of files and folders respectively and although I found a Folder Contents DataSource control, it didn’t cover my needs (like filtering of a folder contents).

I just contributed my solution using .NET Anonymous Types and LINQ (assumes a using System.Linq clause) to:

http://stackoverflow.com/questions/1331793/bind-repeater-to-a-list-of-files-and-or-folders

private string path = HttpContext.Current.Server.MapPath("~/activity");

   protected void Page_Load(object sender, EventArgs e)
   {      
if (!IsPostBack) { //only at page 1st load
listItems.DataSource = Directory.EnumerateFiles(path, "*.clipflair") .Select(f => new { Filename=Path.GetFileName(f) });
listItems.DataBind(); //must call this } }

The above snippet gets all *.clipflair files from ~/activity folder of a web project

Update: using EnumerateFiles (availabe since .NET 4.0) instead of GetFiles since this is more efficient with LINQ queries. GetFiles would return a whole array of filenames in memory before LINQ had a chance to filter it.

The following snippet shows how to use multiple filters, which GetFiles/EnumerateFiles don’t support themselves:

private string path = HttpContext.Current.Server.MapPath("~/image");
private string filter = "*.png|*.jpg";

protected void Page_Load(object sender, EventArgs e)
{
  _listItems = listItems; 
  
  if (!IsPostBack)
  {
    listItems.DataSource =
      filter.Split('|').SelectMany(
oneFilter => Directory.EnumerateFiles(path, oneFilter)
.Select(f => new { Filename = Path.GetFileName(f) })
); listItems.DataBind(); //must call this if (Request.QueryString["item"] != null) listItems.SelectedValue = Request.QueryString["item"];
//must do after listItems.DataBind } }


The snippet below shows how to get all directories from /~video folder and also filters them to select only directories that contain a .ism file (Smooth Streaming content) with the same name as the directory (e.g. someVideo/someVideo.ism)

using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;

namespace ClipFlair.Gallery
{
 public partial class VideoMetadataPage : System.Web.UI.Page
 {

  private string path = HttpContext.Current.Server.MapPath("~/video");

  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack) { //only at page 1st load
listItems.DataSource = Directory.GetDirectories(path) .Where(f =>(Directory.EnumerateFiles(f,
Path.GetFileName(f)+".ism").Count()!=0)) .Select(f => new { Foldername = Path.GetFileName(f) }); //when having a full path to a directory don't use Path.GetDirectoryName //(gives parent directory), //use Path.GetFileName instead to extract the name of the directory listItems.DataBind(); //must call this } }

 

The examples above are from a DropDownList, but it’s the same logic with any ASP.net control that supports Data Binding (note I’m calling Foldername the data field at the 2nd snippet and Filename at the 1st one, but could use any name, need to set that in the markup):

        <asp:DropDownList ID="listItems" runat="server" AutoPostBack="True" 
          DataTextField="Foldername" DataValueField="Foldername" 
          OnSelectedIndexChanged="listItems_SelectedIndexChanged"
          />
%d bloggers like this: