Linq to XML: perform a CRUD operation on XML file

31. August 2010

Let’s get to the point. I have the following XML file called workshop.xml

<?xml version="1.0" encoding="utf-8" ?>
<workshops>
  <workshop name="Workshop 1" />
  <workshop name="Workshop 3" />
  <workshop name="Workshop 5" />
  <workshop name="Workshop 7" />
</workshops>

 

This is how you perform an insert operation, it’s a little bit ugly but it works:

string workshopName = "Some Workshop";
XDocument workshopXML = XDocument.Load(Server.MapPath("~/workshop.xml"));
var workshop = (from w in workshopXML.Descendants("workshop")
                where w.Attribute("name").Value == workshopName
                select w).SingleOrDefault();
if (workshop != null)
    return;
XElement parent = workshopXML.XPathSelectElement("workshops");
XElement newWorkshop = 
new XElement("workshop", new XAttribute("name", workshopName)); parent.Add(newWorkshop); workshopXML.Save(Server.MapPath("~/workshop.xml"));
This is how you perform a delete operation:

string workshopName = "Some Workshop";
XDocument workshopXML = XDocument.Load(Server.MapPath("~/workshop.xml"));
var workshop = (from w in workshopXML.Descendants("workshop")
                where w.Attribute("name").Value == workshopName
                select w).SingleOrDefault();
if (workshop != null)
{
    workshop.Remove();
    workshopXML.Save(Server.MapPath("~/workshop.xml"));
}

Integrating CKEditor in ASP.NET MVC 2

20. July 2010

Not just integrating but also creating an upload functionality for the editor. It’s pretty straight forward but the documentation on CKEditor website is not so complete so I only managed to create both upload and browse functionality in the browse functionality. If you see picture below, I don’t use the Upload tab of the Image Properties, but it works perfectly.

First, if you don’t know how to do file upload in ASP.NET MVC 2, please don’t be lazy to search around or check this blog post from Phil Haack.

Then, download the latest pack from CKEditor website, here’s the link. I am also using the image processing code from my previous post here.

This post will tell you how to create an upload functionality for CKEditor using ASP.NET MVC 2 so that you can use the tab Image Info when you click on the image icon (the same technique can be used to create file browser and upload functionality).

image


Create the Controller

I give it a name UploadController, here’s my code sample:

The first Index Action method returns a collection of images in a specified folder and 3 ViewData objects that holds CKEditor variables.

The second Index Action is the actual Post request that uploaded the image we selected. After successful upload I RedirectToAction to the Index method (please read more about PRG pattern) to avoid re-uploading the image by mistake if user refreshes the page.

public class UploadController : Controller
    {
        #region Images
        //
        // GET: /Admin/Upload/
        public ActionResult Index()
        {
            ViewData["CKEditorFuncNum"] = Request.QueryString["CKEditorFuncNum"];
            ViewData["CKEditor"] = Request.QueryString["CKEditor"];
            ViewData["langCode"] = Request.QueryString["langCode"];

            var dirPath = Path.Combine(Server
.MapPath("~/Content/UploadImages/" + User.Identity.Name)); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } string[] fileNames = Directory.GetFiles(dirPath); List<FileInfo> images = new List<FileInfo>(); foreach (string filename in fileNames) { FileInfo image = new FileInfo(filename); images.Add(image); } return View(images); } [AcceptVerbs(HttpVerbs.Post)] public ActionResult Index(HttpPostedFileBase file,
string CKEditorFuncNum, string CKEditor, string langCode) { if (file.ContentLength > 0) { var dirPath = Path.Combine(Server
.MapPath("~/Content/UploadImages/" + User.Identity.Name)); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } var fileName = Path.GetFileName(file.FileName); var path = Path.Combine(dirPath, fileName); file.SaveAs(path); } RouteValueDictionary rvd = new RouteValueDictionary(); rvd.Add("CKEditorFuncNum", CKEditorFuncNum); rvd.Add("CKEditor", CKEditor); rvd.Add("langCode", langCode); return RedirectToAction("Index", rvd); } }

 

Upload Index View

The Index View of UploadController, this is the upload form. Here’s the code sample:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<List<FileInfo>>" %>
<%@ Import Namespace="System.IO" %>

<!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>Upload Images/Files</title>
    <script type="text/javascript" 
src="/areas/admin/scripts/ckeditor/ckeditor.js"></script> </head> <body> <form action="/Admin/Upload/Index" method="post"
enctype="multipart/form-data"> <label for="file">Image filename:</label><br /> <input type="file" name="file" id="file" /><br /> <input id="CKEditorFuncNum" name="CKEditorFuncNum" type="hidden" value="<%: ViewData["CKEditorFuncNum"].ToString() %>" /> <input id="CKEditor" name="CKEditor" type="hidden" value="<%: ViewData["CKEditor"].ToString() %>" /> <input id="langCode" name="langCode" type="hidden" value="<%: ViewData["langCode"].ToString() %>" /> <input type="submit" value="Upload" /> </form> <hr /> <% if (Model.Count > 0) { foreach (FileInfo image in Model) { string CKEditorUrl = "/content/uploadimages/admin/" + image.Name; string imageUrl = "/admin/upload/images/" + image.Name; %> <a title="<%: image.Name %>" href="javascript:void(0);" onclick="window.opener.CKEDITOR.tools .callFunction(<%: ViewData["CKEditorFuncNum"] %>, '<%: CKEditorUrl %>', ''); window.close();"> <img src="<%: imageUrl %>" border="0" alt="<%: image.Name %>" width="50" height="50" /> </a> <% } } %> </body> </html>

 

Image Thumbnail Viewer

In this example, I use my own thumbnail viewer to generate thumbnail on the fly and render it in the browser using Action method that returns FileStreamResult. Notice the SRC attribute of the image on the picture above is set to “/admin/upload/images/{imagefile}”. Here’s my Action method code sample (see my previous post for the Scale method I’m using):

public ActionResult Images(string id)
{
           // So that I don't need to specify another route.
           string filename = id;

            // Get image filename from Request object.             
            string photoFolder = Server.MapPath("~/Content/UploadImages/admin");
           filename = Path.Combine(photoFolder, filename);
           int width = 150; int height = 150;
           string bg = "#ffffff";

           StreamReader r = new StreamReader(filename);
           ImageDrawing thumbnail = ImageDrawing.FromStream(r.BaseStream);

           MemoryStream ms = new MemoryStream();
           thumbnail = Scale(thumbnail, width, height, bg); 
           thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

           byte[] imageByte = ms.ToArray();

           ms.Dispose();
           thumbnail.Dispose();            
           r.Dispose();

           return File(imageByte, "image/jpeg");
       }

CKEditor Initialization and Configuration

The following is my View that initializes CKEditor and the correct configuration for this example to work. This code should be placed inside the Head tag. Notice that this line is important, filebrowserImageBrowseUrl: '/admin/upload', this is where the image browse functionality will appear when you click on image icon.

<asp:ContentID="Content3"ContentPlaceHolderID="HeadContent"runat="server">
<scripttype="text/javascript"src="/areas/admin/scripts/ckeditor/ckeditor.js">
</script>
<scripttype="text/javascript">
   window.onload = function() {
        CKEDITOR.replace('PostContent',
        {
            toolbar:
            [
                // Your toolbaar configuration here. but make sure that
                // 'Image' is available.

   
                ['JustifyLeft', 'JustifyCenter', 'JustifyRight'],
                ['Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley'],
                ['Styles', 'Format', 'Font', 'FontSize'],                              
            ],               
            filebrowserImageBrowseUrl: '/admin/upload',            
            height : 350,
            ignoreEmptyParagraph : true,                           
            htmlEncodeOutput : true       
       });
    };
</script>    
</asp:Content>


And this is the Html helper that render textarea that will be converted into CKEditor.

<%:Html.TextAreaFor(model => model.PostContent) %>

The same scenario can also be used in ASP.NET Webforms of course. Try it, and if you have problems, don’t hesitate to ask me.

ASP.NET, C#, ASP.NET MVC , , , ,

Using jQuery to Consume Webservice Inside DotNetNuke Module

11. July 2010

In this blog post I will show you how to consume webservices inside a DotNetNuke module using jQuery AJAX functionality. To keep things short, I’m not following the best practice of building DotNetNuke module, so in this example I just create a new project of type ASP.NET Web Application and put this in DesktopModules folder inside my DotNetNuke website root folder. You can use either .NET Framework 3.5 or 4, but I’ll use .NET 4 with Visual Studio 2010 in this example.

image
If you’re new with Visual Studio 2010 and .NET 4, you’ll see that when you create new ASP.NET Web Application, VS2010 will give you a complete working example of an ASP.NET website, I’ll delete the files as I don’t need them now.

image image

Then, I need to add DotNetNuke.dll to my project. This is a module for my existing DotNetNuke site called mydnnsite so I will add the DLL from mydnnsite. Why do I need to add this DLL? Well, to build a module, I need to inherit my UserControl from a PortalModuleBase class that resides in DotNetNuke.Entities.Modules namespace.

Next I add a UserControl (ASCX file) that will host my module user interface, I will call this UserControl View.ascx and then change the inherit class from System.Web.UI.UserControl to PortalModuleBase

Register jQuery from Module


Next step is to inject jQuery library to DotNetNuke by using RequestRegistration method in jQuery class from DotNetNuke.Framework namespace. This will ensure that jQuery will be loaded only once and when necessary.

NOTE: I call the RequestRegistration on each page request in my Module because DotNetNuke won’t remember it after postback event.

See my codebehind below, this is the only code I have for the module View.ascx UserControl.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using DotNetNuke.Entities.Modules;

namespace mydnnsite.jQuery
{
    public partial class View : PortalModuleBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            DotNetNuke.Framework.jQuery.RequestRegistration();
        }
    }
}

 

View.ascx


Below is the HTML markup for the module and also the javascript code.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="View.ascx.cs" 
Inherits="mydnnsite.jQuery.View" %> <script language="javascript" type="text/javascript"> var modulePath = "/DesktopModules/mydnnsite.jQuery"; var serviceUrl = modulePath + "/WebServiceSample.asmx/HelloWorldMethod"; $(document).ready(function() { $("#btnAjax").click(function () { $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: serviceUrl, dataType: "json", data: "{ }", // Passing no data success: function (msg) { $("#content").html(msg.d); }, error: function (msg) { alert(msg.status + " " + msg.statusText); } }) }); }); </script> <input type="button" id="btnAjax" value="Get Content" /> <div id="content"></div>

 

 

The Webservice


Now for the webservice, I’m going to add an ASMX file to my project and write a simple code that returns simple string “Hello World”. I name this file WebServiceSample.asmx. Here is the code of the webservice.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace mydnnsite.jQuery
{
    /// <summary>
    /// Summary description for WebServiceSample
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]    
    [System.Web.Script.Services.ScriptService]
    public class WebServiceSample : System.Web.Services.WebService
    {
        [WebMethod]        
        public string HelloWorldMethod()
        {
            return "Hello World";
        }
    }
}

That’s it for the module. This scenario can be developed further to build even more complex AJAX application.

DotNetNuke , , , ,

Using ASP.NET Upload Control

10. July 2010

In this post, I want to show how to create an upload file feature for your website. It is really basic knowledge but very essential :)
You can control what type of file you want to accept, file size, or you can even upload file with size up to 4MB by default. But in this example I just want to show how to handle a simple upload process.
The code below shows the HTML tag 
image.axd

In the code behind, we have to create an event handler for the button "btnUpload".

using System.IO;

protected void btnUpload_Click(object sender, EventArgs e)
{
        string targetFolder = Server.MapPath("~/UploadedFiles");
        HttpPostedFile uploadedFile = FileUpload1.PostedFile;
        string uploadedFilename = Path.GetFileName(uploadedFile.FileName);
        uploadedFile.SaveAs(Path.Combine(targetFolder, uploadedFilename));
        lblMessage.Text = "File " + uploadedFilename + " is uploaded.";
}
Ok, now that we are set, let me explain line by line here.
string targetFolder = Server.MapPath("~/UploadedFiles"); 
This code simply gets the path to where we want to upload the file to. In this case I have a folder called "UploadedFiles".

image.axd (1)

HttpPostedFile uploadedFile = FileUpload1.PostedFile; 
This code is to get the current file that is being uploaded so that it can be processed further. For example we can check the file extension and size to apply filter if needed. Sample code for this is something like:

if (uploadedFile.ContentLength > 2000000) 
{ 
        // Cannot upload, file is too big, max 2MB 
} 
if (Path.GetExtension(uploadedFile.FileName) != ".pdf") 
{ 
        // Cannot upload, file is not a PDF file. 
} 
The following line of code is to get the filename in the format of "filename.extension" (e.g. "picture.jpg"). The "FileName" properties of HttpPostedFile object is to get fully qualified name of the file on the client, which means the full path of the file on the clients computer, so we need to extract the filename.

string uploadedFilename = Path.GetFileName(uploadedFile.FileName); 
uploadedFile.SaveAs(Path.Combine(targetFolder, uploadedFilename)); 
lblMessage.Text = "File " + uploadedFilename + " is uploaded."; 
The first line of the code above is the actual process of "putting" the file on the server, we save the uploaded file to a destination folder on the server and we also give the file the same filename as it has, we can also define another filename if necessary.
Then next line is just to tell the user that the file has been uploaded successfully.
That was it. It's easy isn't it? Good luck.

Resizing image on the fly with C#

20. March 2009

How often do you face a problem, where you have to process images on the fly? 
At my work, it turns out to be very often, I did this a lot already. Creating function to upload picture is something else, but what to do when a user is uploading a picture, do you want to resize it at that point? or do you want just to upload it and resize it on a later stage. 

Either choice, there are 2 things you can do. First, you can use a ready-made component called ASPJpeg, this solution will just work for you. It also offers a lot of functionalities, you can draw a watermark, resize, create thumbnail, etc. But it is not free. The second option is to write these functions by yourself. It is actually quite easy to do this.

You need:

System.Drawing;
using ImageDrawing = System.Drawing.Image;
And here is the code to resize and scale image: (this code is courtesy of Joel Neubeck)
public static ImageDrawing Scale(ImageDrawing imgPhoto, int Width, int Height, string bg)
{
  int sourceWidth = imgPhoto.Width;
  int sourceHeight = imgPhoto.Height;
  int sourceX = 0;
  int sourceY = 0;
  int destX = 0;
  int destY = 0;

  float nPercent = 0;
  float nPercentW = 0;
  float nPercentH = 0;

  nPercentW = ((float)Width / (float)sourceWidth);
  nPercentH = ((float)Height / (float)sourceHeight);
  if (nPercentH < nPercentW)
  {
    nPercent = nPercentH;
    destX = Convert.ToInt16((Width - (sourceWidth * nPercent)) / 2);
  }
  else
  {
    nPercent = nPercentW;
    destY = System.Convert.ToInt16((Height - (sourceHeight * nPercent)) / 2);
  }
  int destWidth = (int)(sourceWidth * nPercent);
  int destHeight = (int)(sourceHeight * nPercent);

  Bitmap bmPhoto = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

  Graphics grPhoto = Graphics.FromImage(bmPhoto);
  Color c = System.Drawing.ColorTranslator.FromHtml(bg);

  grPhoto.Clear(c);
  grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
  grPhoto.DrawImage(imgPhoto, new Rectangle(destX, destY, destWidth, destHeight), 
    new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
  GraphicsUnit.Pixel);

  grPhoto.Dispose();
  return bmPhoto;
}

The code above can be used together with HttpHandler (a file with .ASHX extension) to generate/resize image on the fly. The idea is to get an image file from file system, and then resize it using the function above and render it to the browser using HttpHandler. The code below shows how to do this.

using System;
using System.IO;
using System.Web;
using ImageDrawing = System.Drawing.Image;

public class imagehandler : IHttpHandler {

  public void ProcessRequest (HttpContext context) {

    context.Response.ContentType = "image/jpeg";

    // Get image filename from Request object. 
    string imgFile = context.Request["file"];
    string photoFolder = context.Server.MapPath("~/some-path-to-imagefile"); 
    imgFile = Path.Combine(photoFolder, imgFile);
    int width = 171; int height = 114;
    string bg = "#ffffff"; 

    StreamReader r = new StreamReader(imgFile);
    ImageDrawing thumbnail = ImageDrawing.FromStream(r.BaseStream);
    thumbnail = Tools.Scale(thumbnail, width, height, bg);
    thumbnail.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
    thumbnail.Dispose();
    r.Close();
    r.Dispose(); 
  }
  public bool IsReusable {
    get {
      return false;
    }
  }
}


Good luck. Let me know if any of you have problem with it.

C# ,

Sending e-mail using ASP.NET

16. November 2007

We sometimes need to send e-mail automatically from our websites or program. In ASP.NET, it is made easier for us to do this task, we will be using classes from System.Net.Mail namespace, they are:

SmtpClient
MailMessage
MailAddress

and if you need to use credential to send e-mail then you also need
NetworkCredential
class from
System.Net
namespace, I will explain in a minute how to use it. The code below will send an email through local SMTP server. Check here for more information about SMTP.

using System.Net.Mail;

SmtpClient smtpClient = new SmtpClient(); smtpClient.Host = "localhost"; smtpClient.Port = 25; 

MailMessage message = new MailMessage(); message.From = fromAddress; message.Subject = "your subject"; //Set IsBodyHtml to true means you can send HTML email. message.IsBodyHtml = true; message.Body = "your message body"; message.To.Add("to@anydomain.com"); 

MailAddress fromAddress = new MailAddress("from@yourdomain.com");

try
{
    smtpClient.Send(message); }
catch(Exception ex)
{
    //Error, could not send the message     Response.Write(ex.Message); } [/code]
That was a code to send e-mail from your local SMTP server, you can try the code above in your development machine. The code below will demonstrate sending e-mail through SMTP server that requires credential/authentication, in this case we need the class NetworkCredential.

[code language="C#"] using System.Net;
using System.Net.Mail;

SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = "mail.mydomain.com";
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = basicCredential;

NetworkCredential basicCredential = new NetworkCredential("username", "password");

MailMessage message = new MailMessage();
message.From = fromAddress;
message.Subject = "your subject";
//Set IsBodyHtml to true means you can send HTML email.
message.IsBodyHtml = true;
message.Body = "your message body";
message.To.Add("to@anydomain.com");

MailAddress fromAddress = new MailAddress("from@yourdomain.com"); 

try
{ 
    smtpClient.Send(message);
}
catch(Exception ex)
{
    //Error, could not send the message
    Response.Write(ex.Message);
}
the line smtpClient.UseDefaultCredentials = false; simply tells the server not to use default network credential, instead, the server should use credential provided in the next line. If you set UseDefaultCredentials to false and you don't provide credential then e-mail is sent anonymously, read this article for more.

ASP.NET, C# , ,

Upload and Convert Video to FLV using ASP.NET and Windows Service

6. May 2007

Recently I did a project to create an application for a big winter vacation agency. It is photo and video uploading website, where people can upload photos/videos and have their friends vote on them. Photo part is easy, what interesting is the video part. I thought it would be as simple as uploading mp3 files and create flash player to load whatever people have uploded, as my colleague told me, but then I realized that it is not as simple as handling mp3 files because videos have to be converted to FLV in order for flash player to play the video. 
I've done a lot of research but I can't find how to stream WMV, MPG directly from flash, they have to be converted to FLV first. I found a really useful tool that can be used to convert almost any video file to FLV, or to image (JPG, PNG, etc.). It is called ffmpeg, it is an executable file (.EXE). The problem is that it is not a good idea to grant permission for ASP.NET account on the server to be able to run executable file. If people find out about this, then your server is in danger, because people can execute command to format your harddrive, for example. 

The solution was to create a simple windows service program or you can also make desktop application to handle all the video convertion process. The code is shown below:



You probably wonder what flvtool is. We use flvtool to index the FLV file in order to add the correct metadata inside FLV file. 
This is actually a simple form of a youtube-like application. You let people upload videos, convert them to FLV and create thumbnails for the preview. However, this kind of technique doesn't work in a shared hosing environment because you usually can't install any program on the server. 

C#, ASP.NET