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...

 






Simple Gantt Chart with Asp.net

by naspinski 6/27/2008 3:33:00 AM

It's very easy to make a Gantt Chart in Asp.Net, just takes a little math

Recently I was asked how to make a Gantt chart in Asp.Net.  Now I am too cheap to actually go and buy some software to do this for me, so I decided to figure it out on my own; can't be that hard right?  I will just use some strategically crafted div's to look like legitimate graphs.  Turns out it really wasn't that tough... wasn't even a lot of code!

 

First thing I did was make some sample data.  Whenever I have used a Gantt Chart in the past, it has been used to plot projects over time.  So my basic elements were:

  • Title
  • Start Date 
  • End Date

 

Now you can have endless extra crap on there, but that is the basics.  Also, instead of dates, you could easily substitute numbers, but I am going to go with dates.  I just produced a DataTable with those as my 3 DataColumns and some dummy data:

 

titlestartend
Super Important Project 6/8/2008 7/3/2008
A Project 6/3/2008 6/30/2008
Crappy Project 6/25/2008 7/3/2008
Party Project 6/13/2008 6/23/2008
Being stupid 6/28/2008 7/8/2008
Getting Hammered 6/18/2008 7/1/2008
Recovering 7/2/2008 7/5/2008

 

Now that we have the data, it is just down to the math of how we are going to get this to work.  First of all, let me explain my approach to CSS graphing: using divs and the css 'width' property can easily make you a horizontal bar graph, just stack a couple divs on top of eachother that are different widths, different backgrounds and there you go, you have some nifty graphs.  The only challenge here is that we can't just use a simple percentage.  The left side of the graph isn't necessarily on the far left side, and with width is going to be relative to where it starts... hmmm.

 

I actually drew this out on some scratch paper on my desk to make it easier to see, using a nice even number: 10.


Now with this information, we can figure out how to render each div (graph line).  Since I am working with DateTime variables, I can easily convert this into TimeSpans and then Days which is an int... then it's easy math.  Notice I added in the *100 up above, that is so I am working with full percentages instead of decimals, like css uses.  Here is the code I cam up with for defining where to start a div and how wide for it to be.  Here is my function that takes in title String, start DateTime and end DataTime  and returns a nicely formatted div.  I am also using the global variables dtMin, and dtMax which are DateTime variables that are the maximum and minimum dates in the data (I use LINQ to find that easily, you can see in the code).  dateSpan is another global variable, an int that is simply (dtMax - dtMin).Days.

 

public string doGantt(object t, object s, object e)
{
    string title = (string)t;
    DateTime start = (DateTime)s;
    DateTime end = (DateTime)e;

    int numberOfDays = (end - start).Days;
    int startDivAt = (start - dtMin).Days > 0 ? (start - dtMin).Days * 100 / dateSpan : 0;
    int howWide = end != dtMax ? ((end - start).Days + 1) * 100 / dateSpan : (end - start).Days * 100 / dateSpan;
    count++;
    return "<div class=\"gantt\" style=\"background:" + colors[count%colors.Count()] + ";width:" + howWide + "%;margin-left:" + startDivAt + "%;\">&nbsp;&nbsp;"+title+"</div>";
}

 

Notice in there I call an array I had declared called colors[] which simply has the colors {"navy","maroon","orange"} in it - this simply rotates the colors of the graph.  The code is pretty straight forward I think; had to do a little magic to prevent it from falling off the edge of the page.  Then to implement it, you just need to add in a repeater in your aspx:

 

<fieldset>
    <legend>Gantt Chart</legend>
    <asp:Repeater ID="rpt" runat="server">
        <HeaderTemplate>
            <div style="font-weight:bold;font-size:1.2em"><%= dateHeader %><br /></div>
        </HeaderTemplate>
        <ItemTemplate>
            <%# doGantt(Eval("title"), Eval("start"), Eval("end")) %></td>
        </ItemTemplate>
    </asp:Repeater>
</fieldset>

 

And then you set your DataSource and DataBind and you have a Gantt Chart...

 

rpt.DataSource = dt;
rpt.DataBind();

 

It even resizes liquidly to the size of the container. It is very vanilla, but definitely a good start to a simple, no images Gantt chart that could be expanded/spruced up very easily!

 


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

asp.net | c# | steal some code | tutorials

Adding Multiple Persistent Controls is Asp.Net

by naspinski 6/16/2008 5:21:00 PM

It's easy to add one control in asp.net during runtime, but it's not so straight-forward to add a bunch dynamically

You would think to add more and more controls, you could simply do something like this on a button click event (I will be using LiteralControls for ease of explanation, but this works the same for all controls, even custom ones):

 

somePanel.Controls.Add(new LiteralControl("<div>I AM A NEW CONTROL</div>"));

 

Which does work perfectly, and does exactly what you think it would do.  But, if you click it again, guess what?  It just re-makes the same control, replacing the old one.  Doing this over and over.  This is because what is produced is not kept in any sort of persistent state.  You need to 'tell' your program what you want it to keep.  For this,  I like to use Session variables... and if you don't like that, then too bad!

 

With that said, we will need some sort of way to keep all the controls in an easily accessable structure.  My choice here is a Generic List as they are so easy to work with and offer so much that you can do do/with them.  To start with, I will be working with a basic List<LiteralControl> but I will get on later to a list with multiple controls contained within it as it is likely that you will want to add multiple controls at each click.

 

Now we just need to show how this is going to be persistant.  First, we need to declare a list in the class.  Then, each time a control is added, it must be pushed into the list as well as the page as to keep a 'copy' of it.  But that still will not survice a postback.  We also need to put the List into a Session variable.  And now that we have that list of controls in the session, we need to check every Page_Load to see if there is any controls we have stowed away, and if so, push them to the page.  Here is the most basic way to show this with functioning code:

 

aspx 

<asp:Button ID="btn" runat="server" Text="Add Control" onclick="btn_Click" />
<asp:Panel ID="pnl" runat="server" />

 

code-behind (c#)

List<LiteralControl> persistControls = new List<LiteralControl>();
protected void Page_Load(object sender, EventArgs e)
{
    // if you already have some controls populated
    if (Session["persistControls"] != null)
    {
        // pull them out of the session
        persistControls = (List<LiteralControl>)Session["persistControls"];
        foreach (LiteralControl lc in persistControls)
            pnl.Controls.Add(lc); // and push them back into the page
    }
}
protected void btn_Click(object sender, EventArgs e)
{
    // basic control for demo
    LiteralControl lc = new LiteralControl("<div style=\"border:solid 2px navy;padding:3px;margin:3px\">NEW CONTROL</div>");
    pnl.Controls.Add(lc);// add it to your page
    persistControls.Add(lc);// add it to the list
    Session["persistControls"] = persistControls; // put it in the session
}

 

Now that is just a basic example to get the point across that this is actually a pretty easy concept.  Now on to a bit more functionality.  There are two basic things I would think an average use of this would require:

 

  • Ability to delete each 'set' of controls
  • Ability to add a bunch of controls each time and persist all of them

 

Turns out both of these are also quite easy given the structure we are using. 

 

Looking at the first one: Ability to delete each 'set' of controls should be no problem as we are using a generic List. What does a List have that makes this so simple?  List.Remove(List Item)  In fact, using a List makes this ridiculously easy.  Simply add a btnDelete_Click method to our code-behind, Now every time a control is added, a Button must also be added with a corresponding CommandArgument that relates to it's position in the List and add a Button.Click += new EventHandler(btnDelete_Click) so the new delete method will be called.  Since the List itself will automatically adjust it's size and move it's items dynamically we can simply use an integer to count up from 0 each time we push a control to the page.  And when a new Control is added, all that is needed is to add the List.Count to the CommandArgument.

 

Now on to: Ability to add a bunch of controls each time and persist all of them which will be even easier.  Instead of passing just one Control like above, we can pass a collection of Controls inside another control.  For this I chose Panels for the easy to work with <div> that they produce.  So now, every time you add a Control, you simply add all your Controls to a Panel, then push that Panel to the List (which is now a List<Panel> by the way).  And really that is all you need to do.  

 

With those two additions, the example code now looks like this:

 

aspx 

<asp:Button ID="btn" runat="server" Text="Add Control" onclick="btn_Click" />
<asp:Button ID="btnClear" runat="server" Text="Reset" onclick="btnClear_Click" />
<br /><br />
<asp:PlaceHolder ID="ph" runat="server" />

 

code-behind (c#) 

List<Panel> persistControls = new List<Panel>();
Random rand = new Random(); // for display so we can get a simple difference in controls
protected void Page_Load(object sender, EventArgs e)
{
    // if you already have some controls populated
    if (Session["persistControls"] != null)
    {
        persistControls = (List<Panel>)Session["persistControls"]; // pull them out of the session
        int count = 0;
        foreach (Panel lc in persistControls)
        {
            lc.CssClass = "smallPanel";
            Button btn = new Button();
            btn.Click += new EventHandler(btnDelete_Click);
            btn.Text = "Delete";
            btn.CommandArgument = count.ToString();
            ph.Controls.Add(lc); // and push them back into the page
            ph.Controls.Add(btn);
            ph.Controls.Add(new LiteralControl("<br /><br />")); // for formatting
            count++;
        }
    }
}
protected void btn_Click(object sender, EventArgs e)
{
    LiteralControl lc1 = new LiteralControl("<span style=\"border:solid 2px navy;margin:3px\"> NEW CONTROL [ "+ rand.Next(1000,9999).ToString() + "] </span>");
    LiteralControl lc2 = new LiteralControl("<span style=\"border:solid 2px navy;margin:3px\"> NEW CONTROL [ " + rand.Next(1000, 9999).ToString() + "] </span>");
    Panel pnl = new Panel();

    pnl.Controls.Add(lc1);
    pnl.Controls.Add(lc2);
    Button btn = new Button();
    btn.Click += new EventHandler(btnDelete_Click);
    btn.Text = "Delete";
    btn.CommandArgument = persistControls.Count.ToString();
    ph.Controls.Add(pnl); // and push them back into the page
    persistControls.Add(pnl);// add it to the list
    ph.Controls.Add(btn);
    ph.Controls.Add(new LiteralControl("<br /><br />")); // for formatting
    Session["persistControls"] = persistControls; // put it in the session
}
protected void btnClear_Click(object sender, EventArgs e)
{
    Session["persistControls"] = null;
    Response.Redirect(Request.Url.ToString());
}
protected void btnDelete_Click(object sender, EventArgs e)
{
    int deleteThisOne = int.Parse(((Button)sender).CommandArgument);
    persistControls.Remove(persistControls[deleteThisOne]);
    Session["persistControls"] = persistControls; // put it in the session
    Response.Redirect(Request.Url.ToString());
}

 

And that is all you need to do.  This could be cleaned up a bit and redundant code could be consolidated, but you get the idea.  This will work with any group of controls be it TextBoxes, DropDownLists or even custom Controls that you make.  I throw mine inside an UpdatePanel to make it function smoother.  Remember though, since this is using Session, high traffic or large control collection can make this a bit of a memory hog, so be careful. 

 

Here is an example and the code:

 



code:


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

asp.net | c# | steal some code | tutorials

WSS 3.0/MOSS 2007 Web Part Tutorial

by naspinski 6/13/2008 4:54:00 AM

So you want to build your own web part eh?

First thing is first, I am going to cut through the crap so you know whether or not you should keep reading right now: for this tutorial to make any sort of sense, you are going to need to have WSS 3.0 and VS/VWD 2008 installed on your Server 2003+ machine; if you do not have one available, make a virtual server (Actually, this is the ideal setup anyway).  You will then need to install WSS 3.0 Extensions for Visual Studio 2008 on your machine (I know I previously posted how to install WSS 3.0 Extensions on your desktop, but that will not work for a full build).  Yes it's a pain, and a lot of requirements, but SharePoint can be a bastard child sometimes.  This really is the hardest part about building new web parts.

Once all of that is out of the way, simply start a new project in VS and choose SharePoint->Web Part.  Give it a name and a location and hit OK.

 

Your solution explorer should now be populated with a bunch of files and references like this:



Now really there are only a few files you need to concern yourself with.  The most important one being the <WebPartName>/<WebPartName>.cs file, in my case it is Test/Test.cs; I will refer to this file as the main file from now on.  I say it is the most important as that is the one that does everything from presentation to code-behind.  The others are the <WebPartName>.webpart file and possibly the AssemblyInfo.cs file, but we will focus on the first right now.


Open up the main file and you will see something like this:



Where you see “TODO: …” is where you are going to put your rendering code.  They even provide you with the always-friendly “Hello World” program if you just un-comment it.  The Guid is automatically populated when you make your project, so don’t mess with it.  The big thing here is that 100% of your styling and layout has to be taken care of back here.  There is no aspx page to your aspx.cs like a normal .net web page.  Once you have a handle on that, it can be treated just like any other asp.net website you have ever made.  There are some other great interactive tools and features you can include, but that is for another day.  Right now, just use the “Hello World” code, use my supplied code or fill it up with your own.

 

NOTE: Often times it is easier to get your programming logic done in a regular Visual Studio Project as there is no way to easily test in a SharePoint Web Part Project.

 

Now that you have your code finished, we can change a few other things.  Open the <WebPartName>.webpart file and you can see some properties you can change.  Customize the Title and Description if you like.



That will change the default settings for this web part.  That is all I would mess with for right now.  So in theory, you now have a 100% working web part.  Now is the easy part.  Just right click on your project and click ‘Deploy’.

 


Assuming everything worked, you know have published your web part to your portal.  If it didn’t work, go fix your bugs and come back :PGo to your Portal->Site Actions->Site Settings->Modify All Site Settings and click on Web Parts under Galleries and you should see your Web Part with a happy little ‘!NEW’ by it.



Now just go to a Web Part Page and put it in there somewhere then exit edit mode.  You should now see your web part in action:


 

Here is my example web part you can take a look at.  It shows a couple different methods of how you can make a web part interact with itself.  As I mentioned above, there is a lot you can do with web parts beyond this, and I will hopefully be able to post some more in the near future.


Source Code:



Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

sharepoint | steal some code | tutorials

Cascading DropDowns using XML and LINQ

by naspinski 5/4/2008 3:12:00 PM

A simple alternative method to the Ajax Control Toolkit's

Don't get me wrong, the Ajax Control Toolkit (ACT) is great, but a couple of the controls leave something to be desired.  For one, the things required to integrate the cascading dropdowns is a bit excessive IMO.  No need ot require asmx files to do a simple lookup.  Also, if you are changing values in your dropdowns (as I needed to do), this gives you no simple way to do it.

 

Figuring that dropdowns are almost always relatively small collections of choices, and I would be editing them often for my purposes, an XML files seems to be the perfect fit for this situation.  On top of that, with the ease of LINQ, this would be extremely easy to make an interface for editing the properties so my users could edit them without knowing the first thing about XML. 

 

I am going to try to basically copy the ACT in terms of functionality as I really like it, but change it 'under the hood'.  First thing is to make a simple XML file with my options in it, I used old cars for an example:

<?xml version="1.0" encoding="utf-8" ?>
<dropdowns>
    <makes>
        <maker>-please select-</maker>
        <maker>Ford</maker>
        <maker>Chevy</maker>
        <maker>Dodge</maker>
    </makes>
    <cars>
        <car_maker name="Ford">
            <car>Bronco</car>
            <car>Galaxy</car>
            <car>Mustang</car>
        </car_maker>
        <car_maker name="Chevy">
            <car>Chevelle</car>
            <car>Corvette</car>
            <car>Nova</car>
        </car_maker>
        <car_maker name="Dodge">
            <car>Charger</car>
            <car>Ram</car>
        </car_maker>
    </cars>
</dropdowns>

 Now add the Dropdowns to yoru .aspx with a few more properies added (required for this to work) the properties are:

  1. cascadeTo : The dropDown you want to cascade to
  2. cascadeCategory : The category in XML your cascade properties lie
  3. cascadeDescendant : The final level in XML where your items lie
  4. cascadeBlank : [optional] What the cascading DropDown will display when it is awaiting a selection


Here is my .aspx, Notice I added "- Select Make -" to the ddlModel DropDownList as that will help give the user some guidance and it is the same as the 'cascadeBlank' I designated:

Make:<br />
<asp:DropDownList ID="ddlMake"  runat="server" cascadeTo="ddlModel" cascadeCategory="car_maker" cascadeDescendant="car" cascadeBlank="- Select Make -"  AutoPostBack="true" onselectedindexchanged="ddlMake_SelectedIndexChanged" />
<br /><br />
Model:<br />
<asp:DropDownList ID="ddlModel" runat="server" Enabled="false"  >
    <asp:ListItem>- Select Make -</asp:ListItem>
</asp:DropDownList>

Next, you need to access your XML document and fill your initial menu, so make sure to add something like this to your code-behind:

XElement x;
protected void Page_Load(object sender, EventArgs e)
{
    x = XElement.Load(Server.MapPath(".") + "\\App_Data\\dropdowns.xml");
    if (!IsPostBack)
        foreach (XElement elem in x.Descendants("maker")) addDdlItems(ddlMake, elem.Value);
}

public void addDdlItems(DropDownList ddl, string value)
{
    ListItem li = new ListItem();
    li.Value = value;
    ddl.Items.Add(li);
}

Now you simply need to call cascade.fromThisDropDown from your _SelectedIndexChange event.  This way you don't need to write any code, just place the cascade.cs fil into your App_Code folder:

protected void ddlMake_SelectedIndexChanged(object sender, EventArgs e)
 { cascade.fromThisDropDown(this.Page, (DropDownList)sender, x); }

And that's it.  You can place it inside an UpdatePanel for the same exact Ajax effect that you have with the ACT, but without those pesky asmx files. If you want to see the cascade.cs code, click here to view/hide.

 

Not completely dummy proof, but I think it's useful.  You can download just the cascade class, or the full working example:






 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

ajax | asp.net | c# | linq | steal some code | tutorials | xml

Updating to SP1 in Sharepoint MOSS 2007 Nightmare

by naspinski 4/11/2008 1:20:00 AM

This 'production' service pack that microsoft released is harder to install than my linux wireless NIC

NOTE

This seems to only be a problem if you are already joined to a server farm, not if it is a fresh install

Ok, I love Microsoft, I might even call myself a fanboy, but this Service Pack 1 is a disaster if you are not working with fresh install.  This is the third time I have had to install it and each time it was a mess, so I am writing it down, step-by-step for anyone who has to go through this.  Keep in mind that this particular install was done on a completely naked 6 server farm with no data on it.  Here is the guide:

 

The first service pack must be the WSS 3.0 Service Pack and must be installed on each machine one-by-one, starting with the Central admin machines. 

 

First trying installing it normally (double clicking on it), THIS STEP IS NECESSARY to continue to the other methods. 

 

If that errors out, try this:

  1. Open a command prompt
  2. Navigate to C:\program files\common files\microsoft shared\web server extensions\12\bin
  3. Type psconfig -cmd upgrade -force

 

If that errors, try this from the same command prompt:

  1. stsadm -o upgrade -inplace -forceupgrade

 

If that errors 

  1. Check the Log file produced - if it complains about not having a web.config file:
  2. Copy the web.config file from the server that hosts the Central admin in the directory: C:\program files\common files\microsoft shared\web server extensions\12\TEMPLATE\LAYOUTS
  3. Paste that to identical directory on the error machine
  4. Run stsadm -o upgrade -inplace -forceupgrade again

 

Once that is installed, install the MOSS 2007 SP1 by double clicking on it, that can be done all machines in the farm at the same time.

 

If that fails: 

  1. Open a command prompt
  2. Navigate to C:\program files\common files\microsoft shared\web server extensions\12\bin
  3. Type psconfig -cmd upgrade -force
    • This will look now for the new failed update, even though the process is the same.
    • You HAVE to try to run it normally for this to work

 

Now you are ready to run the hotfix (wss-kb941422-fullfile-x86-glb.exe)

 

This will install by double-clicking the exe, and should not error out.

 

Now you need to run the Configuration Manager on each machine one-by-one.  And you should be done with the upgrade...

 

LINKS: 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

sharepoint | tutorials

Text Input Watermarks using Javascript (IE Compatible)

by naspinski 4/9/2008 11:52:00 PM

Simple way to add watermarks to your textboxes for a little flair in your input forms

I have always used the TextBoxWatermark control that is supplied with the AjaxControlToolkit which is very easy to use and I highly recommend it.  But recently I was asked to figure out a way without using 3rd party tools, hence in JavaScript.  At first I figured it was going to be simple, just clear the text when you click on the box and maybe change the background color.  Simple, that works.   Thats when I ran into my next problem.

 

I wanted a textbox that was forr passwords, it would start out and say 'password' but then when you clicked on it, that would disappear and it would become a type="password" box (display text as: ******).  It worked flawlessly! ...in non-crappy browsers.  IE7 dumped all over my dreams yet again and left me with a Javascript error.  Turns out you can't change the type property in IE7 (apparently it works in IE6???) which is completely stupid.

 

So, I did some good old googling which brought me here to find out that in order to change type, you now have to make an entire new object and swap it out with the old one.  So after that, it works, but my focus is all screwed up: I click on the blank, the password text disappears, but the cursor is not in the textbox I just clicked?!  That brought me here which showed me a crazy way to reset focus on a lost object:

window.tempObject = newObject;
   setTimeout("tempObject.hasFocus=true;tempObject.focus();",1);

Now everything seems to work just fine.  BUT, they aren't.  For one thing, I had had an onblur statement in my textbox originally (not in the example, but for discussion purposes) and since the new object did not have an onblur, I had to make sure to re-add that back in.  Also, the same loss goes for CSS class, but that might want to change, so I added a new field into the function to take into account a new CSS class.  If it is left blank, it will inherit the old CSS class if there is one, or simply have no class like Britney Spears. 

 

Ok, so I *thought* that would be easy, but IE comes back again to spite me.  For most browsers, you can set Object.setAttribute("onblur", "JSmethod") but IE decides that isn't good enough, so you have to to this Object.onblur = function(){js_function(god, damnit, ie);}; (from this thread).  Ok, now that we have that fixed, we can look at the CSS class.  It's mostly the same, but this is yet another IE specific problem.  You need to include two different declarations: Object.setAttribute("class", "css_class"); for most browsers and Object.setAttribute("className", "css_class"); for IE.  This time the IE fix/hack will not work for cross-browser compatibility.  So here is the finished JS:

 

[code:js]

 function makePassword(oldObject, newClass)
{
    //newclass is the new css class to pass to the textbox
    //otherwise leave it blank ('') to inherit it's old class
    //or if there isn't one, have no class
    var newObject = document.createElement('input');
    //only switched to password if the original text was password
    newObject.type = (oldObject.value == 'password')?'password':'text';
    if(oldObject.id) newObject.id = oldObject.id;
    /// this decided whether to keep the old class or get a new one
    var cssClass = (oldObject.className && newClass.length < 1)?oldObject.className:newClass;
    newObject.setAttribute('className', cssClass);// for IE
    newObject.setAttribute('class', cssClass);// for others (these are both needed)
    //the following is hard coded to add onblur functionality to the control
    //newObject.setAttribute('onblur', 'blurred(this)');// this would work if it wasn't for IE
    newObject.onblur = function(){blurred(this,newClass);}; // because of IE
    oldObject.parentNode.replaceChild(newObject,oldObject);//this is necessary because of IE
    //this is needed since a focus() will only work the second time since it happens too 'soon'
    window.tempObject = newObject;
    setTimeout("tempObject.hasFocus=true;tempObject.focus();",1);
}

 

Remember though that you will have to validate that the original values are not in the textboxes when the user submits, as they will not be empty initially.  Here is a fully working example to mess with, it shows how to use it both for a simple watermark/mask and also with a password field change.  It also includes how to add javascript function calls and deal with changing (or persistent) css:


 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

html | javascript | steal some code | tutorials

Getting the row or sql value/index of the gridview row you just clicked

by naspinski 4/5/2008 9:53:00 PM

Getting the row you just clicked is not as obvious as it seems first hand

There are generally two cases that I need information from the row I clicked in a GridView (or listview, etc.).  The first being simply to get the index in the gridview, whether or not it was the first, fifth or 50th row.  That is pretty easy, but the second case, getting the index (or any) value of the SQL entry of the row just clicked is a little less obvious, though still pretty easy.  Here is a better explanation of that second one if it isn't clear: Say you have a GridView bound to a SqlDataSource (or Linq, etc.) and you have an column in that table that is Product_ID.  Your user is going to click on a button in one of those rows, say it is row 15, but the item Product_ID is 547.  You want to get 547 with no other information than the _Click event.

 

This is how you do it:

 

[code:c#] 

protected void btn_Click(object sender, EventArgs e)
{
   Button btnClicked = (Button)sender;
   // This will get you your GridViewRow
   GridViewRow row = (GridViewRow)btnClicked.NamingContainer;
   // This will get you the actual Index out of your SQL table
   string getIndex = this.GridView1.DataKeys[row.RowIndex].Value.ToString();
   // And this will just print it out to show it works
   Response.Write("Row Index: " + row.RowIndex.ToString() + "<br />");
   Response.Write("Sql Index: " + getIndex);
}

[/code]

 

***IN ORDER FOR THIS TO WORK, you *have to* remember to add DataKeys="Product_ID" to the GridView tag, otherwise you will throw an OutOfBounds exception because your program won't know what the hell you are calling with DataKeys. 

Keep in mind this trick will work for any column in your table. I use this in my own app to populate a modal popup depending on what row was clicked, works very slick. 

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

asp.net | c# | tutorials

Moving ASP.NET roles/membership from Test/Local to Production

by naspinski 4/3/2008 2:18:00 AM

ASP.NET roles/membership providers are incredibly simple and convenient, but if you move you site straight to a production environment (SQL Server, etc.), it's probably not going to work without a couple changes

Believe it or not, I had never needed to use ASP.NET roles in any large production environment.  But recently at work, that changed.  Everything was working great on my local machine, couldn't be smoother, but then I moved everything to our web server with a SQL 2005 backend... no worky.

 

When you enable roles in ASP.NET within VS/VWD it automatically makes an MDF that resides in your App_Data folder.  And most likely, your machine is not running full-fledged SQL, just Express.  Which is just fine, but when you migrate to the production environment, even if you bring the MDF with you and place it in your App_Data file, your roles will not work.

 

What VS is forgetting to tell you is that your membership provider is using an 'invisible' ConnectionString called 'LocalSqlServer' and that that connectionString uses SQL Express and Windows credentials to access it.  Which is why, in most cases, that that connectionString will not work in your production setting.  What you need to do is two things:

 

  1. Move your MDF to you production SQL Server instance
  2. Make sure your role provider references that instance by changing the connection string

 

This is very easy to do, and here is how you do it:

Move your MDF to your Production SQL

  1. Copy your ASPNETDB.mdf file from your App_Code folder to Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data on your SQL machine
  2. Open SQL Server Management Studio and connect to your database
  3. Right click on the 'Databases' folder in the navigation pane, click 'Attach...'
  4. Click the 'Add...' button and navigate to your ASPNETDB.mdf on that machine, click 'OK'
  5. Click 'OK'
  6. You now have it attached and ready to use, I recommend renaming it as the name will be very long (I renamed it simply ASPNETDB.mdf - I'm creative)

Make sure your program references the new database location

  1. Go into your web.config file for your program, locate the connectionStrings section
  2. Add the following 2 lines:
    <remove name="LocalSqlServer"/>
    <add name="LocalSqlServer" connectionString="CONNECTION_STRING_TO_MEMBERSHIP_DB" providerName="System.Data.SqlClient"/>
  3. Upload and you should be all set

The important thing here is that you cleared out the 'invisible' connectionString that .Net uses and replaces it with one that is going to run off of your newly implemented database.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

asp.net | sql | tutorials

Ternary operators simplified

by naspinski 3/21/2008 4:53:00 PM

For a while there, I would see mystical things happening in some code I viewed, and I had no idea what was happening - turn out the bla?bla:bla does mean something, and it is useful and simple

These?are:called ternary operators, and they can be very useful, especially when you want to clean up your code.  A lot of people say that they are hard to read, but I think that is merely because they do not understand how simple they really are. I will show you just how simple they are; here is a statement using a ternary operator:

 

a ? b : c ;

 

And all this means in simple terms is:

 

if a is true, then b is the value of the statement, else c is the value of the statement

 

or if you prefer code:

 

if(a)
  return b;
else
  return c;

 

That really is it, it is that simple. Ternary operators can save a lot of space, and more important (to me) they can easily be used inline, cutting out chunks of code completely.  Take a look at the following for an example:

string s1 = "party";
string s2 = "crom";
string s3 = "arnold";
bool b1 = true;
bool b2 = false;
string s4, s5;

//All of this code:
if (b2)
  s4 = s1;
else
  s4 = s2;

if (b1)
  s5 = s1;
else
  s5 = s2;

//can be replaced by this
s4 = b2 ? s1 : s2;
s5 = b1 ? s1 : s2;

//plus you can easily use it inline
Response.Write("inline = " + (b2 ? s2 : s3).ToString());


You can make them much deeper and more complicated and then they may begin to get difficult to read, but for a lot of everyday tasks, ternary operators are great and space saving!

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

c# | tutorials

Automated Sharepoint Backups including daily folders and trash collection

by naspinski 2/27/2008 1:08:00 AM

SAMS came up with a great SharePoint backup automation tool with their SPSiteBackup.wsf windows script file - it is good, but needed a couple things... so I added them...

The SAMS backup utility is really pretty great.  It runs backups on all of your site collections on a given site as well as as logging the results and emailing the logs to users.  This is very useful, but it is lacking a few features that I felt it needed.

 

First of all, the backup utility put all of the backup files into one directory.  When you have a lot of sites, not to mention if you are backing up MySites, this can become a massive chunk of data.  If you are running this script on any recurring basis, it just turns into a non-decipherable mess of hundreds and hundreds of files, no organization whatosever.  I made a change here that will automatically make folders (named by date) and place the backups in the properly dated folder.

 

Second, there is no garbage collection.  If I ran the script every day, I would eventually choke out all of my storage and be stuck with 100s of GBs of backups.  I could just go in and delete them manually, but no one wants to do that (so 90s).  What if I forget, or go on vacation, or leave Tongue out - so, I made a garbage collection method run within the script as well.

 

All you need to do is place the script file directly on your C: drive, customize the batch file (explanation provided within the .bat file) and schedule it to run (or run it manually) and you are running maintenance-free automatic backups on your SharePoint server/farm.

 

 

 

 

Ok, if you feel ok on your own now, stop reading - if not, read on for a step-by-step tutorial on how to schedule the automated backups on your server...

 

Get the backup script files ready  

  1. Copy the 2 files from the .zip file to the machine you want to run backups on directly to the C: drive
  2. Open spBackup.bat in a text editor, you will see the following:
    cscript c:\spBackupScript.wsf
    /virt:"http://your_sp_site"
    /path:"path_for_backups"
    /smtpserver:"YOUR_SMTP_SERVER"
    /reportto:"send_reports_to@this_email.address"
    /holdfor:"number_of_days_before_backups_are_deleted(integer)"
  3. Change the input variables to what you need them to be (self-explanatory) for that server instance.

 

Now that is set up, you need to schedule the job.

  1. Click Start->Programs->Accessories->System Tools->Scheduled Tasks
  2. Double-click Add Scheduled Task, choose Next
  3. Click Browse... and browse to the .bat file you just edited (C:/spBackup.bat)
  4. Name the task and choose how often to perform the task click Next
  5. Choose the start time click Next
  6. Enter your password click Next
  7. Click Finish

 

It's just that easy, you are now making and cleaning up backups automatically.  Here it is one more time:

 

 

Automated_SP_Backup.zip (3.60 kb)

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

sharepoint | steal some code | tutorials | vb script