This is a method that I’ve used in the past to check for file existence on an FTP server.
Public Function CheckIfFtpFileExists(ByVal fileUri As String) As Boolean
Dim request As FtpWebRequest = WebRequest.Create(fileUri)
request.Credentials = New NetworkCredential("username", "password")
request.Method = WebRequestMethods.Ftp.GetFileSize
Try
Dim response As FtpWebResponse = request.GetResponse()
' THE FILE EXISTS
Catch ex As WebException
Dim response As FtpWebResponse = ex.Response
If FtpStatusCode.ActionNotTakenFileUnavailable = response.StatusCode Then
' THE FILE DOES NOT EXIST
Return False
End If
End Try
Return True
End Function
Get’s called like this:
If CheckIfFtpFileExists("ftp://ftp.domain.com/filename.txt") Then
...
End If
Occasionally I’ve had to troubleshoot sending email messages to a particular SMTP server by simulating a mail client (or .NET mail code) by using the telnet client. Here’s how I do it on Windows:
- open the command prompt
- type: telnet smtpserver.domain.com 25 <press enter>
- type: helo server.com <press enter>
- type: mail from: you@domain.com <press enter>
- type: rcpt to: someone@domain.com <press enter>
- type: data <press enter>
- write a test message. Typically I type something like: hello world! <press enter>
- to send the message type a single period (.) on a line by itself and of course <press enter>
The web slices feature was introduced in IE8 and allows users to subscribe to content directly within a webpage. Web slices allow web site developers to deliver content to the user’s browser no matter what the user is doing. When the content inside the web slice is modified, the user is notified through their Favorites bar and they can respond however they deem appropriate.
To define it, the element that encloses the region of the web slice needs to have the class ‘hslice’ and an unique id. Inside the web slice, items with the class ’entry-title’ will represent the title in the web slice window. Also, items with the class ‘entry-content’ represent the actual content of the web slice.
For those that are interested, the checkin of this code is on the NerdDinner CodePlex site. Here is the markup we created for NerdDinner.com to make the Popular Dinners section of the site available as a web slice.
<div class='hslice' id='2'>
<h2 class='entry-title'>Popular Dinners</h2>
<div class="entry-content" id="dinnerList"></div>
<a rel='feedurl' href='/Dinners/WebSlicePopular' style='display:none;'></a>
</div>
which looks like this when it's rendered on the page:

and looks like this in the Favorites bar:
The code added to the controller class to handle this behavior looks like this:
public ActionResult WebSlicePopular()
{
ViewData["Title"] = "Popular Nerd Dinners";
var model = from dinner in dinnerRepository.FindUpcomingDinners()
orderby dinner.RSVPs.Count descending
select dinner;
return View("WebSlice",model.Take(5));
}
And the View is:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<NerdDinner.Models.Dinner>>" ContentType="text/html" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html401/strict.dtd">
<html>
<head>
<title><%: ViewData["Title"] %><</title>
</head>
<body style="margin: 0">
<div class="hslice" id="webslice" style="width: 320px">
<div class="entry-content">
<center><h2 class="entry-title"><%: ViewData["Title"] %></h2></center>
<div>
<ul>
<% foreach (var dinner in Model) { %>
<li style="list-style-type: none;">
<%: Html.ActionLink(dinner.Title, "Details", new { id=dinner.DinnerID }) %>
on <strong>
<%: dinner.EventDate.ToString("yyyy-MMM-dd")%>
<%: dinner.EventDate.ToString("HH:mm tt")%></strong> at
<%: dinner.Address + " " + dinner.Country %>
</li>
<% } %>
</ul>
</div>
</div>
<a rel="Bookmark" href="http://www.nerddinner.com" style="display:none;"></a>
</div>
</body>
</html>
The MSDN site has some great Web Slice resources, including tutorials to help you get started.
<!--438456cb08694597afa01c826fa2e9f1-->
The release of .NET 3.5 SP1 included the new System.ComponentModel.DataAnnotations assembly as a part of ASP.NET Dynamic Data. They were then included in the ASP.NET MVC2 release. Data Annotations provide a number of attribute classes that allow developers to attach validation logic directly on the model classes through a number of attribute classes. There are 5 validation attributes in the assembly:
- Required - Enables you to validate whether a property has a value.
- Range - Enables you to validate whether a property value falls between a specified minimum and maximum value.
- StringLength - Enables you to validate whether a string is less than a specified maximum length.
- RegularExpression - Enables you to validate whether a property value matches a regular expression pattern.
- DataType - Enables you to verify that a property matches a certain type. Valid types are Custom, DateTime, Date, Time, Duration, PhoneNumber, Currency, Text, Html, MultiLineText, EmailAddress, Password, and URL.
In this example I’m going to focus on the Required, Range, and StringLength attributes. These are basic validators, but cover the majority of basic validation tasks.
Gil Fink, a Microsoft Data Platform MVP, has written Building ASP.NET Validator using Data Annotations, a CodeProject article, that implements a server-side validator. I’ve included Gil’s code here, with some small modifications, for reference.
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Validators
{
[ToolboxData("<{0}:DataAnnotationValidator runat=\"server\"></{0}:DATAANNOTATIONVALIDATOR>")]
public class DataAnnotationValidator : BaseValidator
{
#region Properties
///
/// The type of the source to check
///
public string SourceTypeName { get; set; }
///
/// The property that is annotated
///
public string PropertyName { get; set; }
#endregion
#region Methods
protected override bool EvaluateIsValid()
{
// get the type that we are going to validate
Type source = GetValidatedType();
// get the property to validate
PropertyInfo property = GetValidatedProperty(source);
// get the control validation value
string value = GetControlValidationValue(ControlToValidate);
foreach (var attribute in property.GetCustomAttributes(
typeof(ValidationAttribute), true)
.OfType())
{
if (!attribute.IsValid(value))
{
ErrorMessage = attribute.ErrorMessage;
return false;
}
}
return true;
}
protected Type GetValidatedType()
{
if (string.IsNullOrEmpty(SourceTypeName))
{
throw new InvalidOperationException(
"Null SourceTypeName can't be validated");
}
Type validatedType = Type.GetType(SourceTypeName);
if (validatedType == null)
{
throw new InvalidOperationException(
string.Format("{0}:{1}",
"Invalid SourceTypeName", SourceTypeName));
}
return validatedType;
}
protected PropertyInfo GetValidatedProperty(Type source)
{
PropertyInfo property = source.GetProperty(PropertyName,
BindingFlags.Public | BindingFlags.Instance);
if (property == null)
{
throw new InvalidOperationException(
string.Format("{0}:{1}",
"Validated Property Does Not Exists", PropertyName));
}
return property;
}
protected override bool ControlPropertiesValid()
{
base.ControlPropertiesValid();
if (String.IsNullOrEmpty(SourceTypeName))
{
throw new HttpException(string.Format("The SourceTypeName property of '{0}' cannot be blank.",
this.ClientID));
}
if (String.IsNullOrEmpty(PropertyName))
{
throw new HttpException(string.Format("The PropertyName property of {0} cannot be null.",
this.ClientID));
}
return true;
}
#endregion
}
}
I’ll use Gil’s implementation as a starting point for adding client-side validation using the jQuery validation plugin. I’ll derive my ClientDataAnnotationValidator class from his DataAnnotationValidator class and override the OnPreRender so I can inject the javascript necessary to do the validation. Here’s the code:
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.UI;
namespace Validators
{
[ToolboxData("<{0}:ClientDataAnnotationValidator runat=\"server\"></{0}:CLIENTDATAANNOTATIONVALIDATOR>")]
public class ClientDataAnnotationValidator : DataAnnotationValidator
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (RenderUplevel)
{
if (!Page.ClientScript.IsClientScriptBlockRegistered("__DataAnnotationValidatorMethod"))
{
string masterScript = "\r\n" +
" $(document).ready(function () {\r\n" +
" $('#" + Page.Form.ClientID + "').validate();\r\n" +
" });\r\n";
Page.ClientScript.RegisterClientScriptBlock(typeof(string), "__DataAnnotationValidatorMethod",
masterScript, true);
}
StringBuilder sbAttributes = new StringBuilder();
StringBuilder sbMessages = new StringBuilder();
Type source = GetValidatedType();
PropertyInfo property = GetValidatedProperty(source);
foreach (var attribute in property.GetCustomAttributes(typeof(ValidationAttribute), true).OfType())
{
if (attribute is RequiredAttribute)
{
sbAttributes.Append(" required: true,\r\n");
sbMessages.AppendFormat(" required: '{0}',\r\n", attribute.ErrorMessage);
}
if (attribute is RangeAttribute)
{
RangeAttribute attrImpl = (RangeAttribute)attribute;
sbAttributes.AppendFormat(" range: [{0},{1}],\r\n", attrImpl.Minimum,
attrImpl.Maximum);
sbMessages.AppendFormat(" range: '{0}',\r\n", attribute.ErrorMessage);
}
if (attribute is StringLengthAttribute)
{
StringLengthAttribute attrImpl = (StringLengthAttribute)attribute;
sbAttributes.AppendFormat(" maxlength: {0},\r\n", attrImpl.MaximumLength);
sbMessages.AppendFormat(" maxlength: '{0}',\r\n", attribute.ErrorMessage);
}
}
if (sbAttributes.Length > 0)
{
string clientScriptID = "ClientValidationScript_" + this.ClientID;
if (!Page.ClientScript.IsClientScriptBlockRegistered(clientScriptID))
{
string clientScript = "\r\n" +
" $(document).ready(function () {\r\n" +
" $('#" + this.GetControlRenderID(ControlToValidate) + "').rules('add', {\r\n" +
sbAttributes.ToString() +
" messages: {\r\n" +
sbMessages.ToString() +
" }\r\n" +
" });\r\n" +
" });\r\n";
Page.ClientScript.RegisterClientScriptBlock(typeof(string), clientScriptID, clientScript,
true);
}
}
}
}
}
}
In order to demonstrate how this validator works, we’ll use the following entity class for our testing.
public class Person
{
[Required(ErrorMessage = "ID is required")]
[Range(10, 15, ErrorMessage = "ID must be between 10 and 15")]
public string ID { get; set; }
[StringLength(20, ErrorMessage = "First name is too long!")]
[Required(ErrorMessage = "First Name is required.")]
public string FirstName { get; set; }
[StringLength(20, ErrorMessage = "Last name is too long!")]
public string LastName { get; set; }
[RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*",
ErrorMessage = "Must be a valid e-mail address")]
public string Email { get; set; }
}
Finally, this WebForm demonstrates using the ClientDataAnnotationValidator:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebDataAnnotations1._Default" %>
<%@ Register Assembly="WebDataAnnotations1" Namespace="Validators" TagPrefix="cc1" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/jquery.validate.js"></script>
<form id="form1" runat="server">
<div>
<div>
<asp:label id="lblID" runat="server" text="ID: " />
<asp:textbox id="txtID" runat="server" />
<cc1:clientdataannotationvalidator id="DataAnnotationValidator1" runat="server"
controltovalidate="txtID" sourcetypename="WebDataAnnotations1.Person, WebDataAnnotations1"
propertyname="ID"></cc1:clientdataannotationvalidator>
</div>
<div>
<asp:label id="lblFirstName" runat="server" text="First Name: " />
<asp:textbox id="txtFirstName" runat="server" />
<cc1:clientdataannotationvalidator id="DataAnnotationValidator2" runat="server"
controltovalidate="txtFirstName" sourcetypename="WebDataAnnotations1.Person,WebDataAnnotations1"
propertyname="FirstName"></cc1:clientdataannotationvalidator>
</div>
<div>
<asp:label id="lblLastName" runat="server" text="Last Name: " />
<asp:textbox id="txtLastName" runat="server" />
<cc1:clientdataannotationvalidator id="DataAnnotationValidator3" runat="server"
controltovalidate="txtLastName" sourcetypename="WebDataAnnotations1.Person, WebDataAnnotations1"
propertyname="LastName"></cc1:clientdataannotationvalidator>
</div>
<div>
<asp:label id="lblEmail" runat="server" text="E-Mail: " />
<asp:textbox id="txtEmail" runat="server" />
<cc1:clientdataannotationvalidator id="DataAnnotationValidator4" runat="server"
controltovalidate="txtEmail" sourcetypename="WebDataAnnotations1.Person, WebDataAnnotations1"
propertyname="Email"></cc1:clientdataannotationvalidator>
</div>
<div>
<asp:button id="btnValidate" runat="server" text="Validate" />
</div>
</div>
</form>
ASP.NET WebForms programmers can now use the ClientDataAnnotationValidator to take advantage of DataAnnotations to provide basic client-side and server-side input validation.
Posted
7/21/2010 2:34:35 PM
in
ASP.NET.
ASP.NET 4 had been released for a few months now so I thought that I’d take a look at two new properties added to the System.Web.Page class – MetaDescription and MetaKeywords. These two attributes represent corresponding meta tags in your page and get rendered on the page like so:
<head runat="server">
<title>your DESCRIPTIVE KEYWORDS title goes here</title>
<meta name="description" content="Your keyword rich marketing sales-pitch meta description goes here" />
<meta name="keywords" content="your keywords,go here,separated by a comma,but not a space" />
</head>
Both the description and keywords meta tags can be important in search engine optimization or (SEO). Specifically, Google (and others) use the description meta tag for improving search listings. (For more details, see Improve snippets with a meta description makeover on the Google Webmaster Central blog.) Also, according to Meta Keywords Advice on the Search Engine Guide Web site, Google no longer uses the contents of the keywords meta tag in their search indexes. It’s my understanding that Windows Live Search doesn’t use the keywords meta tag in determining it’s page rankings, but others may, so it doesn’t hurt to build dynamic content in the keywords meta tag.
These new properties may seem a bit trivial, but prior to ASP.NET 4 if you wanted to provide dynamic values for either of these properties you would have to inject the values into the header. There are two ways of doing this. The first is by adding Literal controls into the <head> element and setting their text in the CodeBehind (Method 1). The other was by creating a HtmlMeta control in the code behind and add them to the control collection for the header element (Method 2).
Here’s an example of Method 1:
MetaOld.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="MetaOld.aspx.vb" Inherits="MetaOld" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:Literal ID="metaDescription" runat="server"></asp:Literal>
<asp:Literal ID="metaKeywords" runat="server"></asp:Literal>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
MetaOld.aspx.vb
Partial Class MetaOld
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.Title = "your DESCRIPTIVE KEYWORDS title goes here"
metaDescription.Text = "<META NAME='DESCRIPTION' CONTENT='Your keyword rich marketing sales-pitch meta description goes here'>"
metaKeywords.Text = "<META NAME='KEYWORDS' CONTENT='your keywords,go here,separated by a comma,but not a space'>"
End Sub
End Class
Alternatively, here’s an example of Method 2. Notice that there is no markup required in the aspx page to support this technique:
MetaOld2.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="MetaOld2.aspx.vb" Inherits="MetaOld2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
MetaOld2.aspx.vb
Partial Class MetaOld2
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.Title = "your DESCRIPTIVE KEYWORDS title goes here"
Dim metaDescription As New HtmlMeta
Dim metaKeywords As New HtmlMeta
metaDescription.Name = "DESCRIPTION"
metaDescription.Content = "Your keyword rich marketing sales-pitch meta description goes here"
metaKeywords.Name = "KEYWORDS"
metaKeywords.Content = "your keywords,go here,separated by a comma,but not a space"
Page.Header.Controls.Add(metaDescription)
Page.Header.Controls.Add(metaKeywords)
End Sub
End Class
Since ASP.NET 4, Microsoft introduced the MetaDescription and MetaKeywords attributes in the System.Web.UI.Page class achieving the same behavior is much simpler. You can set these attributes at run time which allows you to generate the content dynamically and provide better descriptions for a particular page (Method 3). Alternatively, you can set the MetaDescription and MetaKeywords attributes declaratively in the @ Page directive at the top of your aspx page (Method 4).
Here’s Method 3, in this example using only the new attributes in the codebehind there isn’t anything needed in the aspx markup to support this.
MetaNew.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="MetaNew.aspx.vb" Inherits="MetaNew" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
MetaNew.aspx.vb
Partial Class MetaNew
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.Title = "your DESCRIPTIVE KEYWORDS title goes here"
Page.MetaDescription = "Your keyword rich marketing sales-pitch meta description goes here"
Page.MetaKeywords = "your keywords,go here,separated by a comma,but not a space"
End Sub
End Class
Method 4, since these attributes are a part of the Page class you can use them declaratively in the Markup as well:
MetaNew2.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="MetaNew2.aspx.vb" Inherits="MetaNew2"
MetaDescription="Your keyword rich marketing sales-pitch meta description goes here"
MetaKeywords="your keywords,go here,separated by a comma,but not a space" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>your DESCRIPTIVE KEYWORDS title goes here</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
An important note: these properties share a couple of behaviors with the Title attribute of the Page class. First, if there are no description or keywords meta tags in the head element, setting either the MetaDescription or MetaKeywords attributes will cause the meta tags are added to the page when it is rendered. Second, if there are already description or keywords meta tags in the head element, the MetaDescription and MetaKeywords attributes will act as get and set methods for the contents of the existing tags.