loads of useful information, examples and tutorials pertaining to web development utilizing asp.net, c#, vb, css, xhtml, javascript, sql, xml, ajax and everything else...

 



Advertise Here
C-Sharpener.com - Programming is Easy!  Learn Asp.Net & C# in just days, Guaranteed!

Translating an Asp.NET site to Another Language Using .resx Files

by naspinski 9/15/2009 10:35:00 AM

translating the .resx files to another language does not require any programming knowledge at all

Translating a properly globalized site in asp.net is simple and does not require the least bit of development knowledge... which is good, because most developers I know barely have a grasp on their own [non-programming] language. This post should probably come after one on how to globalize your asp.net site, but I have an urgent need to explain how to do this first (someone has volunteered to translate my open-source project Slick-Ticket to Spanish; thanks Victor!).

how does it work?

First of all, you should understand how this actually works, it may make it easier. Every page in a site has access to two types of resources (when I say resources here I am referring to strings, words or phrases): Global Resources, and Local Resources - these resources are held in .resx files. Global Resources are commonly used resources that all pages can see, and Local Resources are resources that only a specific page can see. Each language/dialect has a specific code, which you can see here: Language Codes (you can see your default setting in your browser options, for IE, check Tools->Internet Options->Languages). Each page then has place-holders where it will substitute a specific language's resource if it is available. For example, if your browser's settings are set to Mexican Spanish (es-mx) and you are trying to view example.aspx, asp.net will look for the example.aspx.es-mx.resx file to fill in the text. If that file is not present, it will default back down to the default resx file which is example.aspx.resx.

simple enough, how do I edit them?

.resx files are just xml files, and can be edited in a text editor, but that can be very confusing and error prone as there is no syntax and/or structure checking. I recommend you use a program such as Visual Studio if you have it, or Visual Web Developer (free) if you don't; alternatively, there are a few more options such as Mads Kristensen's .NET resource editor application for .resx files, and Resx Editor on SourceForge.

Once you have your editor, just go through and edit the column to be translated, and *ONLY* that one column, messing with the key/name field will break the translation completely.

folder structure

This is the only part that might be a bit confusing. Each folder that contains .aspx, .ascx, etc. files (files with words to be translated) will have their own App_LocalResources folder, and in this folder, there will be a corresponding *.aspx.resx file for each file. Also, any additional languages will be held in a folder with the language abbreviation, and a corresponding file for each file as well. For example, in the admin folder shown here, you can see that it has it's own App_LocalResources folder, in that folder is each corresponding default (in blue) .resx file and there is a folder for each additional language. Here you see the en-us folder (English - United States) and in that you see the same .resx file, but each is named *.en-us.resx (in red) instead of just *.resx. This is the same for each folder, so you will see many App_LocalResources folders. If you forget to change any of them, it will be pretty apparent when you run the program and a lot of stuff does not match up.

Then there is the App_GlobalResources folder in the root; the same thing applies here, just do the same and translate the value column.

Remember that asp.net will first look for your desired language, and use it if it is there, if not, it will drop down to the default.

a couple notes

A couple things to keep in mind, if you see any html markup (not the best practice, but sometimes necessary), remember this:

<do_not_edit>edit_this</do_not_edit>


Also, if you see brackets with a number in them (i.e. {0}, {2}, etc.), be sure to leave those, the developer is using that as a word placeholder.

that's it

Now, as long as it is available, your users will see your site in their preferred language. It is a bit tedious to translate, but much easier than walking through the markup and screwing things up that way. Also, if a resx file is ever missing, it will not error out, it will simply use the default for any parts that are not available.

Parsing/Reading a PDF file with C# and Asp.Net to text

by naspinski 3/16/2009 1:19:00 PM

PDFs are a very ubiquitous and useful file type, but they can be a pain to work with programatically

PDFs are extensively used in my organization, and people always want programs that will extract information from them. It can be very difficult to get the information they want due to the strange format, but sometimes it's a necessity. Here is how to get a PDF into text, from there you are on your own!

download the necessary files

There are always more than one way to skin a cat when it comes to programming, but the easiest way I have found for PDFs is to use the fantastic, open-source project PDFBox. The download is good for all sorts of platforms, but you only need a few parts to use it with Asp.Net and C#.

*Now keep in mind the version numbers I show here may change, but the process should stay the same.

what you need

  • Just a few things, pull the following files into your bin:
    • FontBox-0.1.0-dev.dll
    • IKVM.GNU.Classpath.dll
    • IKVM.Runtime.dll
    • PDFBox-0.7.3.dll

  • Now just make sure you add a couple references in your project, it is a bit of a strange process, so follow it closely. First, add this reference:
    • IKVM.GNU.Classpath

  • Then build the project, as the next reference requires the previous to be built. So you then add this reference:
    • PDFBox-0.7.3

  • Then build again - once again, there may be a better way to do this, but this is what the documentation said and it worked, so I won't mess with it. Now all you need to do is make sure you add the following using statements to any code file that needs to use the parser:
    using org.pdfbox.pdmodel;
    using org.pdfbox.util;

all set, now use it

This quick snippet shows how to use the program to take in a pdf file and output it to a .txt file.  The inputs are simply the string 'pdf_in' which is the path to a PDF to parse, and the string 'txt_out' which is the path to the output text file. You can easily modify it to take in a Stream of some sort or something else like using a FileUpload or output some other way, but this should get the idea across.
public void parsePDF(string pdf_in, string txt_out)
{
    StreamWriter sw = new StreamWriter(txt_out, false);
    try
    {
        sw.WriteLine();
        sw.WriteLine(DateTime.Now.ToString());
        PDDocument doc = PDDocument.load(pdf_in);
        PDFTextStripper stripper = new PDFTextStripper();
        sw.Write(stripper.getText(doc));
    }
    catch (Exception ex) { Response.Write(ex.Message); }
    finally
    {
        sw.Close();
        sw.Dispose();
    }
}

And there you have it, your PDF is now a (most likely, ugly and difficult to parse) text file with your PDF data in it; now it's up to you to figure out how to use it. As you will see, PDFs can (not always) be very strange in how they come out as text, tables will often be in odd order and such and it is a new adventure each time to engineer an effective and acurate parsing scheme that is very case-specific. Normally I would offer a download, but these files are pretty big, so I will leave it to the guys at SourceForge.

Tags: , ,

c# | tutorials

Inserting New Items Into a Table : 'REAL' AJAX with Asp.Net Series

by naspinski 3/15/2009 6:45:00 AM

Add a new item into the table and database and have it immediately sortable, pageable, etc without any postback

This is a continuation of my 'REAL' AJAX with Asp.Net (not Asp.Net AJAX) series posts for those of us trying to stop relying on Asp.Net 'AJAX'.

This is probably the hardest part about a full CRUD (Create, Read, Update, Delete) system, but as we have already covered 'RUD', it's time to hit the 'C'. First of all, we have to break down what will be happening, both on the client-side, and the server side, then it will be easier to dissect.
  1. User pulls up a 'New Entry' dialogue (client)
  2. User enters information and it is validated (client*)
  3. Valid information is sent to the server (client)
  4. Server attempts to add in new item (server)
  5. Server spits back status update (server)
  6. status update is displayed (client)
  7. item is added into the visible table (client)
  8. input fields are cleared and the input dialogue is hidden (client)

The * above denotes that while in this example we are doing only client-side validation, it is in your best interest to add in some server side as well (keep in mind that this example will not work without javascript, so it is not robust and does not 'gracefully' degrade).

As you can see, most of the heavy lifting here is done on the client side, with the dedicated server doing just a couple things.

set up the entry dialogue

First I am adding a couple divs which will be clicked to open the dialogue:

insert.aspx

<div class="button triggerNew">New Entry</div>


In the CSS, you can see that these will render like buttons:

demo.css
.button 
{ 
    width: 100px; 
    font-weight: bold; 
    border: outset 2px blue; 
    padding: 1px; 
    text-align: center; 
    color: Blue; 
}
.button:hover 
{ 
    border-style: inset; 
    cursor: pointer; 
    padding: 2px 0 0 2px; 
}

To go with the whole ajax feel, I am setting up the entry in a modal popup; you probably noticed the class 'triggerNew' which isn't really a css class, but it will be used to by jQuery to hook into any elements that have that class and tie them to the modal. To do that first we must include the jquery.jqModal plugin (which IMO is the best modal plugin as it is minimalist and customizable as well as easy to use) in our masterpage.
demo.master

<script type="text/javascript" src="js/jquery.jqModal.js"></script>


As for the modal popup, here is the markup:

<div class="jqmWindow" id="new">
  <h3 class="modal_header">
    <div class="working">working...</div>
    <a href="#" class="x jqmClose">X</a>
    Add New Entry
  </h3>
  <div class="pad">
    <div class="left">
      <h4>
        <asp:RequiredFieldValidator ID="rfvFirst" ControlToValidate="txtFirst" CssClass="right"
          ErrorMessage="required" runat="server" ValidationGroup="new" />
        First Name
      </h4>
      <input type="text" ID="txtFirst" runat="server" />
    </div>
    <div class="left">
      <h4>
        <asp:RequiredFieldValidator ID="rfvLasst" ControlToValidate="txtLast" CssClass="right"
          ErrorMessage="required" runat="server" ValidationGroup="new" />
        Last Name
      </h4>
      <input type="text" ID="txtLast" runat="server" />
    </div>
    <div class="left">
      <h4>
        <asp:RegularExpressionValidator ID="regAge" ControlToValidate="txtAge" CssClass="right"
          ErrorMessage="1-3 digits" runat="server" Display="dynamic" ValidationGroup="new" />
        <asp:RequiredFieldValidator ID="rfvAge" ControlToValidate="txtAge" CssClass="right"
          ErrorMessage="required" runat="server" Display="dynamic" ValidationGroup="new" />
        Age
      </h4>
      <input type="text" ID="txtAge" runat="server" />
    </div>
    <div class="summary">
      <div id="submit" class="button">Submit</div>
    </div>
  </div>
</div>


Now there is a lot going on there. First of all, I used the Asp.Net validators as we are most familiar with them, and they play nicely with jQuery. Also, I am not using asp:TextBoxes at all, I am sticking with the basic input boxes. But, because I am using the Asp.Net Validators, I still need to include runat="server" with each input that I Validate; this also means that they will get weird Asp.Net IDs and not the exact ones I assign them. All I am doing here is making sure all the fields have values, and that age is a diget with 1-3 digits (yes, someone can be 999 in this system...).

In addition, the css class 'jqmClose' class is included in a link: this will automatically be assigned to close the modal window by jqModal.

I also put an additional 'working' element in there so the user can see that dialogue while the program is running its magic.

But as it stands now, we can't even see that popup, get the validators to fire or submit any sort of data. Here comes the jQuery.

work the jQuery magic

Here is the script, it is explained in the comments:
//assign all 'triggerNew' elements to open the modal dialogue
$('#new').jqm({ trigger: false }).jqmAddTrigger($('.triggerNew'));

//attach this event to the clicking of the 'submit' div
$("#submit").click(function() {
    //will not do anything if the validators don't check out
    //Page_ClientValidate('ValidationGroup') is an Asp.Net generated function
    if (!Page_ClientValidate('new')) { return false; }
    else {
        // get the values from the textboxes into an array
        // notice that this is using .ClientID to get the strange Asp.Net ID assigned to it
        var vals = [
            $("#<%= txtFirst.ClientID %>"),
            $("#<%= txtLast.ClientID %>"),
            $("#<%= txtAge.ClientID %>")
        ];
        // do the ajax post
        $.post(
            //function is at
            "ajax_functions/insert.aspx",
            //send the values frorm the vals object
            { first: vals[0].val(), last: vals[1].val(), age: vals[2].val() },
            function(data) {
                //output the return data
                $("#report").html(data);
                // the class 'success' was sent back if it worked...
                var success = (data.toString().substring(12, 19) == "success");
                //add the new data into the table so the user can see it if it was successful
                if (success) {
                    oTable.fnAddData([
                    vals[0].val(),
                    vals[1].val(),
                    vals[2].val(),
                    '&nbsp;'
                ]);
                    //clear the textboxes
                    $(vals).each(function() { $(this).val('') });
                }
                //hide the modal now that it's done
                $('#new').jqmHide();
            }
        );
    }
});

Note that this will not allowed items added since the last postback to be deleted/edited, that is why the last cell simpy gets an '&nbsp;'. Keep in mind that it is possible, just beyond the scope of this tutorial.

Also, in a ghetto form of error reporting, I passed the css class which will either be 'error' on error, or 'success' otherwise.  We can use that to decide whether or not to post the new data into the table and to clear the inputs.  This will catch any errors that we did not already account for.

Really all that remains is the server-side part, we need to make the page that is called: "ajax_functions/insert.aspx" to handle the inputs passed.

server-side functions

Notice this time that we used a $.post() method, which sends the stated values and returns something - in this case, we are having it return a chunk of html which will tell us what happened with the server, and it will be pushed into the 'report' div. Here is our server operations:

ajax_functions/insert.aspx.cs
using System;

public partial class ajax_functions_insert : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        demoDataContext db = new demoDataContext();
        try
        {
            // get all the new values
            string first = Request.Form[0];
            string last = Request.Form[1];
            int age = Convert.ToInt32(Request.Form[2]);

            //make a new person
            person p = new person()
            {
                first_name = first,
                last_name = last,
                age = age
            };

            //insert them into the db
            db.persons.InsertOnSubmit(p);
            db.SubmitChanges();

            //if it was all successful
            Response.Write("<div class='success'>" + first + " " + last + " [" + age + "] inserted</div>");
        }
        // this will catch all the errors and output an error message if caught
        catch (Exception ex) 
        {
            Response.Write("<div class='success'>Error: " + ex.Message +"</div>");
        }
    }
}

As usual, this is the easy part. Now you have a full working CRUD system, with some pretty good error catching as such with absolutely no postbacks! Ajax is fun and can be quite useful, I hope these tutorials helped make it a little more accessible to some Asp.Net devs, I know I learned a lot making them.

« Deleting

Deleting Items From a Table : 'REAL' AJAX with Asp.Net Series

by naspinski 3/11/2009 1:50:00 AM

Delete an entry from the DB and remove the corresponding row from the table; plus an ajax loading indicator

This is a continuation of my 'REAL' AJAX with Asp.Net (not Asp.Net AJAX) series posts for those of us trying to stop relying on Asp.Net 'AJAX'.

GridView has an incredibly easy 'Delete' feature when used in conjunction with a DataSource, the problem is, that is requires a postback. Since we are going the ajax route, this is a no-go. Alternatively, we could wrap in in an UpdatePanel, but that is exactly what we are trying to avoid. Deleting is very easy, we use a lot of the same methods that were involved in fixing the sort on the last post and using the jQuery .ajax() method.

changes to the markup

First we have to add another column for deleting and stick a delete image in there, this is simple enough. I added unique ids to each row and each delete cell for jQuery to have something to hook on to, you could also add classes. The markup hasn't changed all too much:

delete.aspx

<asp:Repeater ID="rpt" runat="server" DataSourceID="lds">
  <HeaderTemplate>
    <table id="sort_table">
      <thead>
        <tr>
          <th>First</th><th>Last</th><th>Age</th><th></th>
        </tr>
      </thead>
      <tbody>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td id="frst<%#Eval("person_id")%>" class="editable">
        <%#Eval("first_name")%>
      
</td>
      <td id="last<%#Eval("person_id")%>" class="editable">
        <%#Eval("last_name")%>
      
</td>
      <td id="age_<%#Eval("person_id")%>" class="editable">
        <%#Eval("age")%>
      
</td>
      <td style="test-align:right;" id="del_<%#Eval("person_id")%>">
        <img src="images/delete_item.png" alt="delete" />
      </td>
    </tr>
  </ItemTemplate>
  <FooterTemplate>
    </tbody></table>
  </FooterTemplate>
</asp:Repeater>
<asp:LinqDataSource ID="lds" runat="server"
  ContextTypeName="demoDataContext" TableName="persons" />


We put the id on the cell itself and not the image because it will be easier to grab with dataTables, not to mention easier to click.

now for the js

First of all, you will notice if we leave the .dataTables() call the same as before, you can now 'sort' by the last column (the delete column), that isn't right, we have to pass some parameters to our 'dataTables()' method to make sure that column gets ignored:
oTable = $("#sort_table").dataTable({
    "aoColumns": [null, null, null, { "bSortable": false}]
});

Also notice that we decided to store the resulting table in 'oTable' just like the last lesson. Remember that this is because the sortable data is not kept in the table itself, but in an associated array, which we will need later.

Now, using the same method as last time, we will grab the position of the clicked item, attempt the ajax call, but instead of changing a value, we will delete a row. Normally, deleting a row in ajax is very simple, you grab the row by the id, and do a hide() or slideUp(), etc. - but that will not totally work here. Sure it would function, but since we are using sizing and paging, they wouldn't reflect the changes: if you had 30 items in your table, and you were 'showing 10 of 30' items, and you deleted one the normal way, it would still say 'showing 10 of 30 items' when in fact, you are only now showing 9 of 29 items, and the problem then just compounds. The brilliant minds who wrote the dataTables plugin built in ways to get around this.

First thing, we get the position of the clicked item (which all have 'del_' as an id prefix) and store that:
var pos = oTable.fnGetPosition(this);

As well as the id of the cell as we need the corresponding 'person_id' that is contained there:
var del = $(this);

Then we simply call the .ajax() method in jQuery:
$.ajax({
    type: "POST",
    url: "ajax_functions/delete.aspx",
    data: "person_id=" + del.attr('id').replace('del_', ''),
    success: function() {
        $("#report").addClass("success").html("Person Deleted");
        oTable.fnDeleteRow(pos[0]);
    }
});

And that is where the magic happens. It was indicated that this was of type 'POST', the url that it is sent to (we will get to that in a moment), and the POST query that was sent (the delete cell's id, minus the 'del_' prefix). Then, on success, we simply output some feedback to the user into a new div with the id of 'report' - nothing special there. But on the next line, we use the 'oTable' that we stored earlier that has all of the sortable data, and call the included function 'fnDeleteRow' with the position that we collected earlier, and that is what deletes the row. The finished javascript looks like this:

delete.aspx
var oTable;
var aPos;
var editedCell;
$(function() {
    $("td[id^='del_']").addClass("pointer").click(function(event) {
        var pos = oTable.fnGetPosition(this);
        var del = $(this);
        $.ajax({
            type: "POST",
            url: "ajax_functions/delete.aspx",
            data: "person_id=" + del.attr('id').replace('del_', ''),
            success: function() {
                $("#report").addClass("success").html("Person Deleted");
                oTable.fnDeleteRow(pos[0]);
            }
        });
    });
    $(".editable").click(function() {
        aPos = oTable.fnGetPosition(this);
        editedCell = $(this);
    }).editInPlace({
        url: "ajax_functions/update.aspx",
        params: "ajax=yes",
        value_required: true,
        default_text: "click to edit",
        success: function() {
            var data = oTable.fnGetData(aPos[0]);
            data[aPos[1]] = editedCell.html();
        }
    });
    oTable = $("#sort_table").dataTable({
        "aoColumns": [null, null, null, { "bSortable": false}]
    });
});

backend

Lastly is the easy part, to make the backend to "ajax_functions/delete.aspx" to handle the POST.

ajax_functions/delete.aspx.cs
using System;
using System.Linq;

public partial class ajax_functions_delete : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        demoDataContext db = new demoDataContext();
        try
        {
            System.Threading.Thread.Sleep(1000);
            // get the person_id of the person being deleted
            int person_id = Convert.ToInt32(Request.Form[0]);
            db.persons.DeleteOnSubmit(db.persons.First(x => x.person_id == person_id));
            db.SubmitChanges();

            Response.Write("deleted");
        }
        // this will catch all the errors and output them to the edited field
        catch (Exception ex) { Response.Write("Error: " + ex.Message); }
    }
}

This code is pretty simple. Since we specified the POST in the ajax() call in jQuery, we knew the first element of the POST was going to be the person_id, and that is used to delete it from the DB.
*NOTE* that I used a Thread.Sleep() in there which I NEVER recommend using. it is just there to illustrate the ajax loading indicator that was implemented into the masterpage, which is covered next.

ajax loading indicator

I snuck a new div into the masterpage with the id of 'working' and bound it to all jQuery ajax events with the following js:
demo.master
$(function() {
    $("#working").bind("ajaxSend", function() {
        $(this).show();
    }).bind("ajaxComplete", function() {
        $(this).hide();
    });
});

Now any time jQuery is doing ajax, there will be a little notification so the user knows your app is not quitting on them. All other times, that div will be hidden.

Now all that we have left is the ability to add new items.

GridView Sorting/Paging : 'REAL' AJAX with Asp.Net Series

by naspinski 3/8/2009 1:49:00 AM

Who knew this could be so easy... and FAST?

This is a continuation of my 'REAL' AJAX with Asp.Net (not Asp.Net AJAX) series posts for those of us trying to stop relying on Asp.Net 'AJAX'.

Ok, nothing too dramatic to start things off, we are going to make some tabled data sortable and pagable all without using a bit of postback. Not only that, but it is going to be incredibly easy!

First off we need the data that these demos will be working with, nothing complicated, just a simple SQL table 'person' that holds peoples' names and ages:

setup.sql
CREATE TABLE dbo.person (
person_id INT NOT NULL PRIMARY KEY IDENTITY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
age INT NOT NULL
);

Also included in the setup.sql file is some dummy data to populate it initially. We ill be using a Linq as our datasource throughout with a .dbml file named demo.dbml.

Next we need to display the data. Normally if I wanted to do paging, I would use a GridView, due to the fact is is already integrated. But that integration is sloooow, and requires a postback - we are ajax'ing here! What we are going to do will load all the data (which could be slower initially on large data sets) and use jQuery to take care of all of the lifting for us. So, it is much more efficient for us to use a Repeater. Without postbacks, all the advantages of a GridView quickly fade away. You will see how little markup you need:

sort_page.aspx

<asp:Repeater ID="rpt" runat="server" DataSourceID="lds">
  <HeaderTemplate>
    <table id="sort_table">
      <thead>
        <tr><th>First</th><th>Last</th><th>Age</th></tr>
      </thead>
      <tbody>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td><%#Eval("first_name")%></td>
      <td><%#Eval("last_name")%></td>
      <td><%#Eval("age")%></td>
    </tr>
  </ItemTemplate>
  <FooterTemplate>
    </tbody></table>
  </FooterTemplate>
</asp:Repeater>
<asp:LinqDataSource ID="lds" runat="server"
  ContextTypeName="demoDataContext" TableName="persons" />


That is all the markup it takes, no code-behind. Now just call the javascript magic of the combination of jQuery and the extension dataTables:

sort_page.aspx
$(function() {
    $("#sort_table").dataTable();
});

And just like that you have a full sortable (with flipping sorting images), filterable, sizable, pageable and 'pretty' table using a simple Repeater. Now, I guess this isn't truly ajax, as nothing is truly pulled from the data store after the initial pull, but I argue that it is *relatively* because if you were to use a GridView jumping pages would cost a postback each time.

This is just the introduction here, but it is to show you how incredibly easy it is to get real, time-saving ajax and it is not as intmidating as you think. Next I will be showing you how to do inline editing of this table.

Shout it Update »