Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Thursday, August 27, 2009

ComicsInventory.com

I just wanted to share a little project I've been working on called ComicsInventory.com.

I have been a big fan of comic books for years and have over the years accumulated a very large collection. Sometime ago I decided to start organizing my collection and finding out how much each issue was worth. I looked around the net for a solution but found very over priced solutions or free solutions that had very bad interface designs or poorly written code. This gave me the opportunity to merge my love of comics with my love of code. Plus I figured I could use the site as a testing ground for anything new that comes out in the coding world ;-)

For my framework I decided to use (at the time) the beta of Asp.net MVC. I liked the freedom it gave you and its minimalistic design. It's faster, lighter and gets you back to html and http. No server controls or viewstate! But I've already talked about this before.

Since theres so many different ways to organize comics. I decided to build the site around a labeling system. This gave me the flexibility to assign multiple labels to comics and group them in different categories. A side benefit that came about was when I added the "total price" feature. This made it very convenient when getting values for all your spider-man comics. But also if some of those spider-man comics were CGC'd. I could create a CGC label and see how much all my CGC comics were worth.

Another big feature is the Image Viewer and Image Upload. This was tricky because I had to reliably upload an image, create 2 copies (1 large & 1 thumbnail) and upload those images to Amazon's S3 service. All in 1 step. I used the awesome flash plugin Uploadify to constrain the image sizes and handle the image upload to the site. I then used the .NET image classes to copy and resize the images. Instead of making my own Amazon S3 library I decided to use ThreeSharp. This library was fantastic and had an active discussion section.

Designing the interface and the look of the site was very important to me. I wanted the site to be very clear, easy to use, but also minimalistic. I spent time at 37signals, studying there site but also there philosophy on feature creep and really focusing in on what features are important to ship with first. It helped a lot with designing the Home page where I wanted to show what the site was about.

I learned a lot about the MVC architectural pattern, designing and using third party services to extend your site. But the best thing is I now have a place to inventory my comics and in the process created a service that others can benefit from.

Site Architecture

Core
  1. OS: Windows Server 2008
  2. Web: IIS 7.0
  3. Database: SQL Server 2008
  4. Language: C#

Dev Tools
  1. IDE: Visual Studio 2008 Team
  2. Framework: ASP.NET MVC
  3. Data Access helper: Microsoft Enterprise Library
  4. Browser Framework: jQuery
  5. Source Control: Subversion
  6. Subversion Client: AnkhSVN
  7. Compare Tool: WinMerge

Third party libraries
  1. Uploadify - flash plugin to handle uploads & constraints
  2. ThreeSharp - Amazon S3 library
  3. Json.NET - JSON Serializer/Deserializer
  4. Google Analytics - web site statistics
  5. UserVoice - feed back system

Tuesday, May 26, 2009

Using jQuery Plugin Uploadify with Asp.net MVC

Just started using this great jQuery plugin called Uploadify, that lets you upload multiple files to the server. It uses flash to queue the files and send them one by one to the server. Plus provides feedback and all other types of goodies. The implementation is pretty straight foward.

Just add this client side code.

<script type="text/javascript" src="/Content/js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/Content/js/jquery.uploadify.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#fileInput").uploadify({
uploader: "/Content/swf/uploadify.swf",
script: "/UIImageViewer/Upload",
cancelImg: "/Content/imgs/cancel.png",
auto: true,
folder: "/uploads",
onError: function (a, b, c, d) {
if (d.status == 404)
alert("Could not find upload script. Use a path relative to: "+"<?= getcwd() ?>");
else if (d.type === "HTTP")
alert("error "+d.type+": "+d.status);
else if (d.type ==="File Size")
alert(c.name+" "+d.type+" Limit: "+Math.round(d.sizeLimit/1024)+"KB");
else
alert("error "+d.type+": "+d.text);
}
});
});
</script>
<body>
<input type="file" name="fileInput" id="fileInput" />
</body>


Then create a controller with a "Upload" action.
  public string Upload(HttpPostedFileBase FileData)
{
/*
*
* Do something with the FileData
*
*/
return "Upload OK!";
}


The tricky part, which drove me crazy, is that you need to use the "HttpPostedFileBase" class NOT the "HttpPostedFile" class. If you use the other class the script will return a "IO Error #2038" error message.

Tuesday, February 3, 2009

Sending email in C# using GMail!



Here is some code I put together to send email using your Gmail account.
This can come in handy if you want your app to send notifications and you don't have access to an SMTP server.

Remember there is a limit that Gmail puts on mass emails. They will punish you if you go over it.

Gmail Sending Limits
In an effort to fight spam and prevent abuse, Google will temporarily disable your account if you send a message to more than 500 recipients or if you send a large number of undeliverable messages. If you use a POP or IMAP client (Microsoft Outlook or Apple Mail, e.g.), you may only send a message to 100 people at a time. Your account should be re-enabled within 24 hours.



Remember to set "DeliveryMethod = SmtpDeliveryMethod.Network". If this is not set then Gmail will come back with a "client was not authenticated" error.

Code
using System.Net.Mail;
using System.Net;

var fromAddress = new MailAddress("from@gmail.com", "From Name");
var toAddress = new MailAddress("to@yahoo.com", "To Name");
const string fromPassword = "password";
const string subject = "test";
const string body = "Hey now!!";

var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword),
Timeout = 20000
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
smtp.Send(message);
}

Sunday, November 4, 2007

Single & Multiline TextBox with MaxLength Validation

After doing a bit of searching online I couldn't find an easy way to control the character length in a text box and a multi line text box. Plus the limit is defined by the schema of the table in a database. So I did what any developer would do with this problem. I used it as an excuse to write some code!

Here is one example of limiting characters in a text box or a multi line text box in a asp.net form. This example will also show how to add a dynamic warning message once the limit has been reached.

This example has 3 parts.

  • A Stored Procedure

  • Some C# code

  • A Javascript function



Lets get into the code!

Create the stored procedure

CREATE PROCEDURE [dbo].[GetFieldWidths]
(
@TableName nvarchar(40)
)
AS
BEGIN
SELECT COLUMN_NAME,
CHARACTER_MAXIMUM_LENGTH,
DATA_TYPE
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = @TableName
END
RETURN

Create a C# function to read all valid fields widths into a Generic Dictionary Collection.



// helper function
public static Dictionary FieldWidths
{
get
{
System.Web.HttpApplicationState ApplicationState = HttpContext.Current.Application;
if (ApplicationState["cDatabase.Tables.tblUsers.FieldWidths"] == null)
{
ApplicationState["cDatabase.Tables.tblUsers.FieldWidths"] = cDbaseFunc.FieldWidths(tblUsers.TableName);
}

return ApplicationState["cDatabase.Tables.tblUsers.FieldWidths"] as Dictionary;
}
}

// main function
public static Dictionary FieldWidths(string Table)
{
//Load field types
string[] aryStringTypes = new string[6] { "char", "nchar", "ntext", "nvarchar", "text", "varchar" };
List StringTypes = new List(aryStringTypes);

Database db = DatabaseFactory.CreateDatabase();
DbCommand dbCommand = db.GetStoredProcCommand(cDatabase.StoredProcedure.GetFieldWidths);
db.AddInParameter(dbCommand, "@TableName", DbType.String, Table);
IDataReader dr = db.ExecuteReader(dbCommand);

string FieldName = string.Empty;
int FieldLength;
string FieldType = string.Empty;

Dictionary FW = new Dictionary();
while (dr.Read())
{
FieldType = dr.GetString(2).ToLower();
if (StringTypes.Contains(FieldType))
{
FieldName = dr.GetString(0);
FieldLength = dr.GetInt32(1);
FW.Add(FieldName, FieldLength);
}
}
dr.Close();

return FW;
}

Create the Javascript function that limits the characters and creates the dynamic message.



function CheckCharMaxLenLimit(control,maxlength)
{
var ErrorMsgID = control.id + "_$MAXLENGTH_ERROR_MSG$";
var ErrorMsg = document.getElementById(ErrorMsgID);

var MaxLength;
if(maxlength != null)
{
MaxLength = maxlength;
}
else
MaxLength = control.maxLength - 1;

var TextLength = control.value.length;
if(TextLength > MaxLength)
{
control.value = control.value.substring(0,MaxLength);

if(ErrorMsg == null)
{
control.outerHTML = control.outerHTML + MaxLength + " character limit!";
}
}
else
{
if(ErrorMsg != null)
ErrorMsg.parentNode.removeChild(ErrorMsg);
}
}

The final step is too attach the javascript function to your text box control "onkeyup" event.
You can do this in the code behind like so....
this.txtUserName.Attributes["onkeyup"] = "CheckCharMaxLenLimit(this," + this.FieldWidths["Username"] + ");";

Summary


The nice thing about the C# function is that it caches the returning list of fields and widths into an Application State variable. If your tables schema changes allot you could always cache it in a session state variable. This reduces the hits to SQL server which improves performance.

The character limiting and checking is handled on the client side using the javascript function. This function also supports the "maxLength" attribute of the text box control. The dynamic message is also created on the client side by using the DOM to attach a child element to the text box. This creates a very quick UI response. Lastly the dynamic message can be formatted using standard CSS.

Like so...
.MAXLENGTH_ERROR_MSG
{
color:red;
}

This method uses SQL2005 but I'm sure it could easily be used with any database platform. I hope this helps someone out there with the same problem.

Wednesday, September 19, 2007

SQL Server 2008 Spec sheets are OUT!!

Well it looks like Microsoft has released the new spec sheets on SQL Server 2008 and man there is a lot of sweet stuff they have added.

Here are the highlights..

  • Policy-based Management
    A framework that enables policies to be defined for explicit and automated administration of server entities across one or multiple servers.


  • New Language Integrated Query (LINQ) extensions
    This enables developers to be more productive by working with logical data entities that align with business requirements instead of programming directly with tables and columns.


  • Beyond relational data
    New data types such as a geospatial type, filestream type, 4 new data & time types and a Hierarchy ID type have been added.



Another really cool feature that will help in the swelling of database sizes is the addition of Sparse columns. Its a highly efficient way of managing empty data in a database by enabling NULL data to consume no physical space.

I'm sure all the GIS nerds out there are chopping at the bit to get there hands on the new geospatial functionality. Well its here and it looks very promising.

Check out some of the features below...

Comprehensive Spatial Support

  • Work with geodetic and planar data types
    Implement Round Earth solutions with the geography data type; using latitude
    and longitude coordinates to define areas on the Earth’s surface. Implement
    Flat Earth solutions with the geometry data type; storing polygons, points,
    and lines that are associated with projected planar surfaces and naturally
    planar data, such as interior spaces.


  • Build on industry standards
    Import and export spatial data in industry-standard formats, such as Well
    Known Text, Well Known Binary, and Geographic Markup Language (GML).


  • Perform spatial operations
    Use the methods provided by SQL Server 2008 spatial data types to write
    Transact-SQL code that performs operations on spatial data, such as finding
    intersections between geospatial objects and distances between locations.


High Performance Spatial Data Capabilities

  • Store large and complex spatial objects
    Use the spatial types in SQL Server 2008 to accommodate spatial objects,
    regardless of whether the objects are simple or very complex.


  • Build high-performance solutions with spatial data indexing
    Enhance query performance by using indexes for spatial data that are
    integrated into the SQL Server database engine. Take advantage of accurate
    query optimizer cost assessment for spatial queries that can determine the
    optimal query plan and identify appropriate index selection.


  • Consolidate relational and spatial data in business applications
    Use the native support for spatial data types in SQL Server 2008 to
    seamlessly incorporate spatial data into line-of-business applications.



Geospatial Application Extensibility

  • Build spatial solutions of any scale
    Take advantage of spatial support in multiple editions of SQL Server 2008,
    from SQL Server Express to SQL Server Enterprise Edition.


  • Use spatial standards support to integrate applications
    Leverage a .NET-based geometry library that supports OGC standards. Build
    applications that consume and manipulate spatial data. Integrate with
    geospatial services, such as Microsoft Virtual Earth™, to build
    comprehensive location-enabled solutions that render your spatial data for
    display.


  • Benefit from spatial community support
    Take advantage of spatial products and services offered by Microsoft
    partners that integrate with SQL Server 2008.


These are just the highlights. There is a ton of additional enhancements and features they've added that's really worth looking at.
Get more info here...SQL Server 2008