Share This!

Saturday, August 30, 2008

Use Tables, not CSS

The following 2 shots are of Firefox and IE, and they illustrate how designing layouts with CSS (div tags with style sheets positioned to produce a column or flow layout) DOES NOT WORK the same way in all browsers.

CSS for layout sounded like a great idea, it just didn't deliver on it's promises. Tables do.


This is Firefox fucking up my CSS layout.


To my understanding of CSS, this is how it should look - how it does look in IE.

Wednesday, August 27, 2008

The Comprehensive ASP.NET Development Checklist

The point of this post is not that it is a comprehensive checklist, but rather that it will become one. I mostly write it because I got tired of skipping the same old steps every freaking time I created a new website. So without further ado, here is the list.
  • APPLICATION NAME: Will your application require it's own app name? if so, create it on your web server NOW. This will simplify the whole authentication thing if you're using ASP.NET authentication.
  • MEMBERSHIP AND ROLES PROVIDERS: - if you are using them check here for info on doing this. In general you do not want to use a site database, they are way too slow.
  • SETUP SITE DEFAULTS: Use the App Config screens to assign an email account to your web server. Verify that this works with AO-Hell!
  • PAGE TITLES: Make sure every aspx page has a title.
  • favicon.ico: Make sure your site has a 16x16 icon. These can alternately be loaded in the page's headers if you need different icons for each page.
  •  SSL Certificates (optional)
  • Turn off Debug Mode
  • Lock-down your Administration site
  • Review robots.txt
  • table CSS to table-layout: fixed; (if you don't want your tables expanding on you)

Monday, August 25, 2008

Windows XP: Service Pack 3

...Sucks.

Before this critical patch I would leave my computer going 24/7 for weeks without problems. I have Carbonite and I like to let it do it's backups all night long.

But since the upgrade, I have to reboot 3 times a day AND I come in every morning to find that my Internet connection has frozen up. I would call Microsoft to complain, but I don't have $450 to spend on a service call.

I can feel the Linux adrenaline building in my bloodstream.

Friday, June 27, 2008

Choosing Another Database for Membership and Roles


By default, Visual Studio Express likes to store all its membership and roles data in a local user instance provider called AspNetSqlProvider that uses a database called ASPNETDB.MDF in your APP_DATA directory in your project. This type of database is called a user instance.
I think it would be beneficial to expose some terms here.
  • provider: this is an asp.net object that supplies information to the website software. There can be numerous providers in an application and a provider doesn't necessarily connect to a database. It could just as easily connect to an XML file, a text file, a random number generator or a golden retriever...
  • membership: is the information about members, i.e. login, password, email address, etc.
  • roles: This data can be kept separate from the membership data and describes what roles are assigned to each user (admin, guest, moderator, whatever) It also contains information about what roles have access to which features in your site.
  • user instance: This is a database stored in your APP_DATA directory. There are severe performance issues with this type of database, and many ASP hosts do not support user instances.
  • MSSQL Express: This is the free version of Microsoft SQL Server Database (MSSQL). even though a user instance database is this type of a database, in this article MSSQL Express database refers to a database created with SQL Server Management Studio Express tools. These databases are not a part of your website, but can be accessed by one or more websites. The data does not exist in your website folders and must be published separately.
  • MSSQL: Microsoft SQL Server is the full paid version of SQL server (the one you'll probably use on your live website if you are a corporate developer, or you're using a professional ASP.net web hosting service.
Ok. So you (like me) want to stop Visual Web Developer from using the user instance, and tell it to use a MSSQL Express database, and you do not want to write your own provider objects. Here is the step by step plan to do this.

Create a New Database

This assumes that you are not using an already existing database... if you already have a MSSQL Express database you can skip this step. Just open SQL Server Management Studio Express (download it if you don't already have it) and create an empty database.

Add the Membership and Roles Tables

There is a special program you can use for this, but you must learn the secret handshake. This program is part of the .NET framework and resides in your .net folders. The program name is Aspnet_regsql.exe and I suggest you find it by browsing to C:\WINDOWS\Microsoft.NET\Framework and doing a search for Aspnet_regsql.exe. On my system I find one copy of it in the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 folder (strangely not in the v3.0 or v3.5 folders).
Launch the program.
Click Next.
Select Configure SQL... and click Next.

The Server is the Windows name of your computer, but WAIT, don't pop open that Database list or you'll get the dreaded...
Connection failed
Failed to query a list of database names from the SQL server. An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
...error.
This is not Microsoft's finest work, and this is where you must know the secret handshake I mentioned earlier. You must alter your Server Name to make this tool recognize that we're using SQLExpress. Add \SQLEXPRESS to the end of your computer name. Mine reads THEDOCTOR\SQLEXPRESS.  It also worked to use .\SQLEXPRESS.  Note also that if you named your SQL server something else when you installed it, you need to use that name.  The pop-down list will be enabled to open and there will be a list of all the databases on your machine.
Databases can be shared across machines too - in case your database isn't on the same machine that you develop on.

Select your new database and click Next.
Review and if all is well, click Next again.
Click Finish.

The database is ready for you to create membership and roles info. Now all we have to do is...

Tell web.config about the new database.

There are 3 steps for this.
  1. create a connection string.
  2. hook up the Membership provider.
  3. hook up the Roles Manager.
Here are the sections of my web.config that worked.

1. The Connection String

<connectionStrings>
<add name="MYDATABASE" connectionString="Data Source=THEDOCTOR\SQLEXPRESS;Initial Catalog=AFIDatabase;Integrated Security=True" providerName=".NET Framework Data Provider for SQL Server" />
</connectionStrings>
The bold text should be changed to reflect your database and server names. The name property (in green) will be needed to identify the connectionstring to the providers.

2. The Membership Provider

<membership defaultProvider="MyProvider" userIsOnlineTimeWindow="30">
<providers>
<clear/>
<add connectionStringName="MYDATABASE" applicationName="/" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" name="MyProvider" type="System.Web.Security.SqlMembershipProvider" />
</providers>
</membership>
The clear removes any references to the default databases from machine.config.
Note that the Membership object contains the definition of the provider which contains a reference to the connection string. The applicationName property is used to identify the application - you can share this name across many websites to allow a single signon for many sites.
So the membership object uses the MyProvider provider which uses the MyDatabase database.
( Membership object -> MyProvider -> MyDatabase )

3. the Roles Manager

<roleManager enabled="true" defaultProvider="MyProvider">
<providers>
<clear/>
<add connectionStringName="MYDATABASE" applicationName="/" name="MyProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
Note that even though I named the provider MyProvider again, it is in fact a different object. However, this allows me to use the Single Provider setting in the website settings page in Visual Web Developer.
Now if you open the ASP.NET Configuration page from Visual Web Developer (Website - ASP.NET Configuration) and click the "Providers" tab, then the "Single Provider" option, you should see the new provider you just created, and it should already be connected.
If the configuration page crashes for any reason, there are a few things to try.
  • ensure that the names of your providers match the "defaultProvider" property exactly.
  • ensure that you have used the same applicationName everywhere.
  • ensure that the connectionStringName in your providers exactly match the name in your connectionStrings section.

For Further Reading

Many thanks to Rob Mills and Guru Bhai for their help figuring this out.

Tuesday, June 17, 2008

Using A Different Database as a Membership Provider in ASP.NET

There should be no need for me to ask this but after 2 days of ditzing around trying to make this work I am at the end of my patience. Linux is looking better all the time.

Ok, I created a website with security and it works great on my desktop, the performance sucks (utterly) on the test webserver, and I cannot use it at all on the production server. That's because we must use real MSSQL in production rather than a user instance, the production environment does not support user instances.

All I need is to tell my membership, role, and security objects, "Look over here, not over there". One would think that altering a connectionstring and replicating the membership tables would be all thats needed.

But NO.

Plus, I can't seem to find a comprehensive tutorial on this anywhere, so I'm mixing info from blogs and msdn and whatnot trying to make this work. Most of the tutorials out there are for MSSQL2000 (I'm using 2005) and a mix of ASP.NET 2.0 and 3.5 (Im using 3.5 - I think)

Here is what I want.

On my workstation, I want the authentication to look in my local MSSQL Express database for ALL security info.

In Production, I want the web server to look in the FULL MSSQL database for this info.

I do NOT NOT NOT want to re-engineer membership and roles objects.

Here's what I have found so far.

http://msdn.microsoft.com/en-us/library/sx3h274z.aspx - generic - no specifics

http://msdn.microsoft.com/en-us/library/6e9y4s5t.aspx - this adds my new database to the MEMBERSHIP selection but not the Single Provider or Role Provider

http://msdn.microsoft.com/en-us/library/2fx93s7w.aspx - This helps you create the table structure in your database, but leaves out 1 critical piece of info... the fact that I had to type "/sqlexpress" after the server name or it crashes when you try to drop down the list.

http://forums.asp.net/p/980214/2369556.aspx - This is where I found out you have to type "/sqlexpress"

http://msdn.microsoft.com/en-us/library/ms998317.aspx - not sure if "Forms Authentication" is what I'm doing or not...

Friday, June 6, 2008

Extreme Frustration with XML

Ok, given the following XML...
<?xml version="1.0" encoding="utf-8" ?>
<queries>
    <query name="MatchUser1">
        <sql>
            SELECT     st_abbr AS state, lic_number AS licensenumber, lname AS lastname, fname AS firstname, zip
            FROM         GovtRegistry
            WHERE     (st_abbr = @STATE) AND (lic_number = @LICENSE) AND (fname = @FIRSTNAME) AND (lname = @LASTNAME) AND (zip LIKE @ZIP)
        </sql>
    </query>
    <query name="MatchUser2">
        <sql>
            SELECT     st_abbr AS state, lic_number AS licensenumber, lname AS lastname, fname AS firstname, zip
            FROM         GovtRegistry
            WHERE     (st_abbr = @STATE) AND (lic_number = @LICENSE)
        </sql>
    </query>
</queries>

How do I do this?

  XmlDocument document = new XmlDocument();
  document.Load("SomeFile.XML");
  XmlNode myQuery=document.find("MatchUser1");

  //this should give the text from the "sql" field of MatchUser1.
  string SQL = myQuery["sql"].value;  

What am I missing here? All I can find online is how to manually walk from node to node, testing the types of the nodes. The whole point of XML used to be that it was simple to organize, store, and retrieve data!

Azeez wrote:
Hi Bryan,
I came across your  resume and was interested in speaking to you in regards to an 
opportunity with  one of my clients. Iam interested in reviewing your resume and 
having a  conversation to see if we can potentially work together. I would appreciate
if  you can send me a word version of your most updated resume and a number to reach 
you by during the day.

Job Title:     Web UI  Developer
Location:     Ann Arbor,  MI
Duration:     6 Months contract 2 hire
Job openings:
One opening for network programmer focusing on User  Interfaces (UI) for Network 
switches.
User interfaces include WEB UI, CLI,  and SNMP.
The applicant must have experience in embedded system WEB  UI.
The GateD user interface programmer must have a strong desire to work  with network 
protocols and user interfaces. 

Education Requirements are: 
Bachelors in Computer Science or  Computer Engineering with and 2-5 years of 
Experience, or Masters in Computers  Science and 1-3 years of experience.

Applicants for the job should have the following skills: 
Strong C  skills,
PERL, Python, TCL, Shell Scripting,
Experience with Apache Web  server
Be familiar with Cisco’s Command Line interface,
Strong skills in  operating systems and experience with embedded operating systems,
Have a  strong theoretical background in network software with 3+
upper classes in  networking, routing protocols,
Have strong background and experience in  creating user interfaces, 
Applicant should have a strong background  in: TCP/IP,  Routing protocols (RIP, 
RIPng, 
OSPF (v2/v3), BGP, IS-IS, PIM,  MSDP), Switching protocols (STP, RSTP, MSTP, 
802.1aq, TRILL), Wireless protocols  (802.11, military radios),
Strong background in 802.11 Wireless devices  (CAPWAP),
Experience writing Network Management protocols (SNMP, XML, Agent  X, SMUX, etc.),
Experience with Web servers (Apache),
Experience with the  Linux operating system,
Experience with embedded operating systems, 
Strong theoretical background in compilers and debugging tools, 
Experience with routers (cisco, juniper, 3com, extreme), and 10G switches  
(Force-10),
Experience with wireless controllers (Cisco, Trapeze),   and
Theoretical and practical experience creating network test  automation

Personal requirements:
The GateD project works in a high connected team  with multi-site development.
Individuals applying must be self-pace,  self-learning, and have experience working 
with teams.
Individuals must have  strong verbal skills with an ability to quickly come to 
resolution of  inter-personal and technical issues.

All groups with the GateD project operate on a team-approach.
The  project requires strong software discipline in software process (specification, 
 coding, and test).
The project is looking for team members who want to  advance their skill set and 
become industry leaders in routing.

Thanks & Regards,
Azeez Khan | Azeez@catamerica.com | Azeez.cat@gmail.com

Sr.Technical Recruiter | CAT Technology Inc.
"Committed to Human  Excellence Through IT"
Hasbrouck Heights, New Jersey. 

Office: (201) 255-0319 Ext : 279 | Fax: (201) 727-9296
www.catamerica.com

http://www.catamerica.com

Azeez: I have highlighted the skills I have in green, and those I lack in red. If you had really seen my info online, you would have already known this.

  Applicants for the job should have the following skills: 
 Strong C  skills,
 PERL, Python, TCL, Shell Scripting,
 Experience with Apache Web  server
 Be familiar with Cisco’s Command Line interface,
 Strong skills in operating systems and experience with embedded operating systems,
 Have a strong theoretical background in network software with 3+ upper classes in  networking, routing protocols,
 Have strong background and experience in  creating user interfaces, 
 Applicant should have a strong background  in: TCP/IP,  Routing protocols (RIP, RIPng, OSPF (v2/v3), BGP, IS-IS, PIM,  MSDP), Switching protocols (STP, RSTP, MSTP, 802.1aq, TRILL), Wireless protocols  (802.11, military radios),
 Strong background in 802.11 Wireless devices  (CAPWAP),
 Experience writing Network Management protocols (SNMP, XML, Agent  X, SMUX, etc.),
 Experience with Web servers (Apache),
 Experience with the  Linux operating system,
 Experience with embedded operating systems, 
 Strong theoretical background in compilers and debugging tools, 
 Experience with routers (cisco, juniper, 3com, extreme), and 10G switches  (Force-10),
 Experience with wireless controllers (Cisco, Trapeze),   and
 Theoretical and practical experience creating network test  automation

It's pretty obvious that what you did was not come across my resume, rather you harvested my email address and are blasting this out to 10,000 people hoping for a hit. If you did your job (for the money a broker gets, I expect this), you would not have bothered me with this. As it is, you just come across as lazy. I don't work for lazy agents.

Wednesday, May 28, 2008

Reconsidering Tables

My blog layout was all CSS. Then I made a simple change and suddenly the blog content started rendering below the sidebar for Firefox only. I started monkeying with the stylesheet and noticed a lot of "fixes" for certain behaviors in IE or Netscape or Firefox.

That's when it hit me. The whole "css, not tables" movement is a false religion, whose promises are nothing but a pipe-dream. Tables behave in a predictable way on every browser. Divs do not.

Easy SQL to Insert the states and territories into a Lookup Table

This has been tested in MSSQL.
truncate table states;

--STATES
INSERT INTO states (state, st) VALUES('ALABAMA','AL');
INSERT INTO states (state, st) VALUES('ALASKA','AK');
INSERT INTO states (state, st) VALUES('ARIZONA','AZ');
INSERT INTO states (state, st) VALUES('ARKANSAS','AR');
INSERT INTO states (state, st) VALUES('CALIFORNIA','CA');
INSERT INTO states (state, st) VALUES('COLORADO','CO');
INSERT INTO states (state, st) VALUES('CONNECTICUT','CT');
INSERT INTO states (state, st) VALUES('DELAWARE','DE');
INSERT INTO states (state, st) VALUES('DISTRICT OF COLUMBIA','DC');
INSERT INTO states (state, st) VALUES('FLORIDA','FL');
INSERT INTO states (state, st) VALUES('GEORGIA','GA');
INSERT INTO states (state, st) VALUES('HAWAII','HI');
INSERT INTO states (state, st) VALUES('IDAHO','ID');
INSERT INTO states (state, st) VALUES('ILLINOIS','IL');
INSERT INTO states (state, st) VALUES('INDIANA','IN');
INSERT INTO states (state, st) VALUES('IOWA','IA');
INSERT INTO states (state, st) VALUES('KANSAS','KS');
INSERT INTO states (state, st) VALUES('KENTUCKY','KY');
INSERT INTO states (state, st) VALUES('LOUISIANA','LA');
INSERT INTO states (state, st) VALUES('MAINE','ME');
INSERT INTO states (state, st) VALUES('MARYLAND','MD');
INSERT INTO states (state, st) VALUES('MASSACHUSETTS','MA');
INSERT INTO states (state, st) VALUES('MICHIGAN','MI');
INSERT INTO states (state, st) VALUES('MINNESOTA','MN');
INSERT INTO states (state, st) VALUES('MISSISSIPPI','MS');
INSERT INTO states (state, st) VALUES('MISSOURI','MO');
INSERT INTO states (state, st) VALUES('MONTANA','MT');
INSERT INTO states (state, st) VALUES('NEBRASKA','NE');
INSERT INTO states (state, st) VALUES('NEVADA','NV');
INSERT INTO states (state, st) VALUES('NEW HAMPSHIRE','NH');
INSERT INTO states (state, st) VALUES('NEW JERSEY','NJ');
INSERT INTO states (state, st) VALUES('NEW MEXICO','NM');
INSERT INTO states (state, st) VALUES('NEW YORK','NY');
INSERT INTO states (state, st) VALUES('NORTH CAROLINA','NC');
INSERT INTO states (state, st) VALUES('NORTH DAKOTA','ND');
INSERT INTO states (state, st) VALUES('OHIO','OH');
INSERT INTO states (state, st) VALUES('OKLAHOMA','OK');
INSERT INTO states (state, st) VALUES('OREGON','OR');
INSERT INTO states (state, st) VALUES('PENNSYLVANIA','PA');
INSERT INTO states (state, st) VALUES('RHODE ISLAND','RI');
INSERT INTO states (state, st) VALUES('SOUTH CAROLINA','SC');
INSERT INTO states (state, st) VALUES('SOUTH DAKOTA','SD');
INSERT INTO states (state, st) VALUES('TENNESSEE','TN');
INSERT INTO states (state, st) VALUES('TEXAS','TX');
INSERT INTO states (state, st) VALUES('UTAH','UT');
INSERT INTO states (state, st) VALUES('VERMONT','VT');
INSERT INTO states (state, st) VALUES('VIRGINIA','VA');
INSERT INTO states (state, st) VALUES('WASHINGTON','WA');
INSERT INTO states (state, st) VALUES('WEST VIRGINIA','WV');
INSERT INTO states (state, st) VALUES('WISCONSIN','WI');
INSERT INTO states (state, st) VALUES('WYOMING','WY');

--TERRITORIES
INSERT INTO states (state, st) VALUES('AMERICAN SAMOA','AS');
INSERT INTO states (state, st) VALUES('FEDERATED STATES OF MICRONESIA','FM');
INSERT INTO states (state, st) VALUES('GUAM','GU');
INSERT INTO states (state, st) VALUES('MARSHALL ISLANDS','MH');
INSERT INTO states (state, st) VALUES('NORTHERN MARIANA ISLANDS','MP');
INSERT INTO states (state, st) VALUES('PALAU','PW');
INSERT INTO states (state, st) VALUES('PUERTO RICO','PR');
INSERT INTO states (state, st) VALUES('VIRGIN ISLANDS','VI');

--CANADA


INSERT INTO states (state, st) VALUES('Alberta','AB');
INSERT INTO states (state, st) VALUES('British Columbia','BC');
INSERT INTO states (state, st) VALUES('Manitoba','MB');
INSERT INTO states (state, st) VALUES('New Brunswick','NB');
INSERT INTO states (state, st) VALUES('Newfoundland and Labrador','NL');
INSERT INTO states (state, st) VALUES('Northwest Territories','NT');
INSERT INTO states (state, st) VALUES('Nova Scotia','NS');
INSERT INTO states (state, st) VALUES('Nunavut','NU');
INSERT INTO states (state, st) VALUES('Ontario','ON');
INSERT INTO states (state, st) VALUES('Prince Edward Island','PE');
INSERT INTO states (state, st) VALUES('Quebec','QC');
INSERT INTO states (state, st) VALUES('Saskatchewan','SK');
INSERT INTO states (state, st) VALUES('Yukon','YT');

Sunday, May 25, 2008

ASP: Adding info to user profiles.

First: this is NOT a tutorial on adding security to your website. It's really about adding additional info to user profiles in ASP.net once you have created the profile.

It all started when I was asked to add some site-specific data to user profiles for a job. I wanted to add a license number (and some other fields) as part of our validation process.

Here is the short version for those who just want to make it work. All the examples here are in C# and ASP.NET 2008.

Quick Summary

First open your web.config file and find .

Right after that add a few lines. This example shows my own License Number field.

<profile>
  <properties>
    <add name="LicenseNo" type="System.String"></add>
  </properties>

Ok, that adds the spot for this data to the Profile object. Now here's what you do to access the data.

TextBox Example:

Make an ASP.Net AJAX web page in a secured directory. Then add this:

<asp:textbox id="tbLicense" runat="server"></asp:textbox>

Now click the Textbox and Select events from properties. Double click Init and create this handler (If you don't get the lightning bolt icon for events in the properties window, read this).

 protected void tbLicense_Init(object sender, EventArgs e)
 {
     tbLicense.Text = Profile.LicenseNo;
 }

Now add a handler for textchanged.

 protected void tbLicense_TextChanged(object sender, EventArgs e)
 {
     Profile.LicenseNo = tbLicense.Text;
 }

You could make the update happen on a button click if you like but I wanted immediate updates when the user changes the field. So go back one more time to the aspx page and on tbLicenseNo change AutoPostBack to True.

Now run your page.

DropDownList Example:

Here is an example with a dropdown list for account types.

in web.config

<add name="AccountType" type="System.string">

in the aspx page

<asp:dropdownlist id="AcctType" runat="server" autopostback="True" 
   oninit="AcctType_Init" onselectedindexchanged="AcctType_SelectedIndexChanged">
   <asp:listitem text="Customer" value="Customer"></asp:listitem>
   <asp:listitem text="Vendor" value="Vendor"></asp:listitem>
   <asp:listitem text="Investor" value="Investor"></asp:listitem>
   </asp:dropdownlist>

now the handlers

protected void AcctType_Init(object sender, EventArgs e)
  {
     string s = Profile.AccountType;
     AcctType.Items.IndexOf(AcctType.Items.FindByText(s));
  }
protected void AcctType_SelectedIndexChanged(object sender, EventArgs e)
  {
     Profile.AccountType = AcctType.SelectedValue;
  }

Done.

Detailed explanation:

What's happening? There is an object named Profile associated with every web hit. Note that I didn't have to create an instance of it or load it from anywhere. It's just there. Note what happens in the C# source when you type Profile. The context help pops up the names of the data items you added in the web.config file.

Now open up your aspnetdb.mdf database. The data are stored in the aspnet_Profile table. I do not recommend editing this data on your own through SQL. It's much easier to modify it via the asp.net profile object.

Monday, May 5, 2008

Graphics Question

This would be easy in Delphi, but I can't seem to get the objects I want to do what I need.

Ok, I have a function that creates and draws a maze on a Panel in a Winforms App. Then I sniped some code that manages to save the image of the panel to a bmp file.

WHY it's any harder than panel.canvas.savetofile is just stupid.

BUT!

If the panel is off the screen edge, or if it's obscured in any way, I get blank rectangle on the image (again stupid).

What I really want is what I've had for 10 years in Delphi.

I want to make my routine create the image in memory (even if the image is bigger than the screen). I want to be able to...

1. copy that image to the panel during a paint event

2. save the entire image to a file.

What I have run into so far is typical Microsoft.

First there are too may objects and no cohesive tutorial. I have tried the following objects.

  • Graphics. I can't create one linked to a memory bitmap.
  • Image. Nope you can't create one of these either.
  • PaintEventArgs you can create one but you can't use it.
  • Bitmap Nope I cnt get it to work.
What I want is this...
something MyPaintObject=new something(width, height, pixelformat);
MyPaintObject.clear(color);
MyPaintObject.fillrect(); 

...etc. Just regular paint commands

Then I want to be able to do this:

During a panel paint event: panel1.copyfrom(MyPaintObject);

...and when I want to save it, MyPaintObject.SaveToFile(filename, Bmp);

---

Ok, I got the answer: Here it is: thanks to a kind poster on the Microsoft forums.

Here's the Post: Graphics Question

Here's the answer.

Bitmap myBitmap = new Bitmap(200, 200, PixelFormat.Format24bppRgb);

public void DrawBitmap()

{

using (Graphics myGraphics = Graphics.FromImage(myBitmap))

{

myGraphics.Clear(Color.AliceBlue);

Pen Bic = new Pen(Color.Blue);

myGraphics.DrawEllipse(Bic, new Rectangle(0, 0, 199, 199));

}

}

private void panel2_Paint(object sender, PaintEventArgs e)

{

DrawBitmap();

e.Graphics.DrawImage(myBitmap, 0, 0);

}

Wednesday, April 30, 2008

Using Subversion with Visual Web Developer

*Note: this method doesn't just work for Visual Web Developer, it should work for any software where source files are stored on your local drives. This includes C#, C++, Java, VB, Delphi, C++ Builder, Flash, Poser, etc.

This tutorial will get you started using Tortoise SVN to easily back up and version your websites. If you don't know why this is a great idea, then you've never screwed up your projects so bad that you wasted 3 days trying to get it back to where you started.

Step 1

Find a spot to back up your stuff. I use an external USB drive. There are also ways to do this over the intranet and Internet. You can store your archive (subversion calls this a repository) on your main hard drive, or another computer in your network as well.

Step 2

Download and install Tortoise SVN for windows. Once installed, right-click nearly any file on your system and note the new options that are available (Don't select them yet, just *note* them).

Step 3

Create a folder on your archive drive to put a project in. In my case, on the external drive it's named like this: I:\subversion\Website1.

Then navigate to the parent folder and right-click the project archive folder (in my case this was I:\subversion) and right-click the new archive folder (Website1). Choose TortoiseSVN - Create Repository Here. Select Native Filesystem (FSFS). This takes a few 10ths of a second, and creates files and folders in the archive folder.

Step 4

Now browse back to your websites folder (the place where you have the files to be archived) and right-click the project you want to check in. Select TortoiseSVN - Import. It is important to note that to Tortoise, import means "import to the archive" and export means "Pull it out of the archive". In the import dialog select the archive folder you just created (such as file:///I:/Subversion/Website1. Click OK. The contents of your project will be imported into the repository. Click OK.

Now whenever you change a file in your project, you can upload the changes to the repository, and if you mess it up, you can roll it back in an instant! I'll do more tutorials about using Tortoise SVN later.


Apologies for the delay...

Yes, you must use tortoise to check out the project again. I suggest checking it out to a new folder. There are some Windows sharing settings that will cause errors here if you are saving to a shared drive. I am still looking into this.

Saturday, April 26, 2008

Error: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

When accessing a SQL Database from an ASP.NET page, I sometimes get this error:

Error: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

... This seems to be because the SQL Server isn't spun up all the time like Oracle is. So initially after a long pause it seems to take a lot longer to set up again.

There are 2 possibilities here, one is that you are timing out before a connection is made, and the other is that your command is taking too long to execute.

Connect Timeout Set the Connect Timeout to a much higher value, like 120.

ComandTimeout Set the CommandTimeout to a much higher value.

Tuesday, April 15, 2008

MSSQL Update Trigger Example

This tutorial shows how you would create a trigger in Microsoft SQL Server 2005/2008 that will date/timestamp a column named last_updated everytime any data in the row is updated.

This example assumes a primary key that includes 3 fields.

CREATE TRIGGER MyTableUpdate
ON dbo.MyTable
FOR update
AS
UPDATE
MyTable
SET last_updated = GetDate()
From MyTable Inner Join Inserted On
MyTable.KeyField1 = Inserted.KeyField1
and MyTable.KeyField2 = Inserted.KeyField2
and MyTable.KeyField3 = Inserted.KeyField3

Thursday, March 20, 2008

Missing Event Handlers

First, has anyone other than me noticed that it takes like 2+ minutes for Visual Web Developer to fully open and come alive? What the hell is it doing? We'll save that for another time.

So you create an Ajax Web Form. You want to put an even handler on Init of the form. How? There is no event icon in the object inspector for the document.

So you click on the Script manager and presto! you get the little lightning bolt icon.

Let's try it with a master page. We create a master and a content page and guess what? There is NO WAY to add an onInit handler to the content page. There's no script manager. If you open the .cs code file and/or double-click the page in the designer, you get a page_load function.

You can try to add one by hand, but where would you put that?....

Ok lets move on.

Slap a button on the screen, and then select the button. Wohoo! the little lightning bolt is there!

Now create a table and put in a row and a cell and put the button in there. Oops, you can no longer click the button and create event handlers, you keep getting the table. In fact the only way I have found to add a handler is to drag the button out of all the panels, tables, etc., and edit it's event handlers, then drag it back into it's table cell and hope it all works.

This is goofy.

The solution is to create all components you need to access the events of outside all tables tables or panels, create the event handlers and then drag (or cut/paste) the objects back into the table or panel.

Tuesday, March 11, 2008

IE7 Displays Blank Page: Firefox OK.

When I try to browse to my website, which contins an ASP page, I get a blank page for IE7, yet all is well for Firefox.

View Source in Firefox gives the normal page, while IE just shows this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; 
charset=windows-1252"></HEAD>
<BODY></BODY></HTML>

The page had some Flash embedded, but I get this result even after removing it. Im heading for "Clearly, IE is BROKEN". What MORON would have a browser substitute a blank page without any kind of error or warning message?


I found the solution after pulling an all-nighter on it.

This had to do with a database error: here's what happened. For some reason the database error was NOT getting reported to the browser, it just got a blank page.

I store the data from every hit in a table for diagnosing problems. That data element was a varchar(250), which up until now was more than adequate. The string from a firefox hit comes in at 163 and looks like this:

03/10/2008 16:24:14 Mozilla Netscape 5.0 (Windows; en-US) Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12 en-US Win32

However IE7 sends this for the exact same page:

03/10/2008 16:24:14 Mozilla Microsoft Internet Explorer 4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.590; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.590; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) undefined Win32

That's a whopping 380 characters, which caused a string length error on my SQL insert command.

I still don't understand why in hell it returned a completely blank page to IE without any errors listed but whatever, I'm re-doing the whole site in ASP.NET anyways.

The ANSWER: I had to stretch the database column where I'm storing the hit data strings to 1000 characters. That ought to hold me until IE8 SP2 at least.

Thursday, March 6, 2008

ASP.NET: Uploading Files

This is so easy. Drop a FileUpload object onto your AJAX web page. Drop in a button.

In the button event handler, do this:

//get the path to the UPLOADS directory in your webbserver
        string path=Server.MapPath(@"~\Uploads"); 

//create the full path+file name
        string SaveAsName=path+@"\"+FileUpload1.FileName;

        try
        {

//This is the bulk of it right here.
            FileUpload1.SaveAs(SaveAsName);
        }
        catch(Exception err)
        {
            Label1.Text = err.Message;
        }

That's it. The FileUpload object hands you all the data and functionality you need. Of course I could have checked to see that the file being uploaded is of a certain size or type, but this quick tutorial is just about the basics.

Sunday, February 17, 2008

Permissions...

This article is about setting up private, member-only areas of your website that are either for admins or clients to access. The .net framework gives several easy ways to set this up with a minimal amount of coding.

Assuming you already have a website, and wat to add a restricted zone, do this:

First, enable permissions for your website

WebSite->ASP.NET Configuration
Browse to the security tab.

There are essentially 3 things to configure: Users, Roles, and Access. By default this data is stored in a MSSQL database in your website's folder structure.

I like to enable roles first, creating roles like client, admin, mod, or whatever. This process is easy enough. For this tutorial, create a user, and give it the admin role. Now before we can add access, we'll close the config screen and return to our project.

Create a folder



Add any html or aspx web page to the new folder. Add a link to the new page to your main website.

If you run the website now, you get free access to the new page (we haven't limited access yet).

Return to the ASP.NET Configuration and on the security tab, click Manage Access Rules.

Click on the new admin directory and then add allow permission for admin role. Then add deny permission for all.

The way this works is that this list is accessed from top to bottom, looking for a permission to apply. The first match that is found is applied. Therefore if we gave the deny - all permission first, then nobody would have any access to the folder.

The Login Page

By default, the login page is named login.aspx. This page will load any time that the client doesn't have sufficient privileges to access the page asked for. It must be in the unprotected part of your website.

So create a new page named login.aspx. Add in a login and password recovery gizmo from the login tab of the toolbox. Click on the gizmos and use the Auto Format function from the pop-out box to select the perfect style.

That's it.

Now anytime the user tries to access a page that he's not logged in for, he first gets the login screen. If he is already logged in, he gets the screen he asked for without interruption.

It's cool. I know.

Saturday, February 9, 2008

ASP.NET How to open a URL in a pop-up window.

Note: if you just want the browser to open a page in another browser page, look up the target parameter of the a href tag.

If you just want to pop a quick message box, look up the javascript alert function.

This article demonstrates how to pop up a new browser window on the click of a hyperlink and load whatever page you want in a controlled browser window.

In the head portion of your page , put the following javascript function.


<script language="javascript">function Pop(URL){
  a=window.open(URL,'MyWindow','status=0,toolbar=0,width=300,height=250');
  a.focus();
  return false;} 
</script>

AJAX NOTE:this can be in the AJAX master page, or in the "Content1" head section of the content page, as I show here.)

Then create a link in the body of your article, like this:


<a onclick="return Pop('htmlpage.htm')" href="http://www.blogger.com/">Test the popup feature</a>

Here's the details of how this all works.

URL: Within the function: We pass in the URL to open from our call to the function. The URL can be any html, shtml, or aspx page.

window.open: Call this javascript function and give it a URL, a window name (the html name of the document) and the opening parameters. You can use the name parameter to control the number of popups. For instance, if we created 10 links all naming the same name (like "MyWindow"), then they will all load in the same pop-up window. If we create 10 links all naming different windows, then each hyperlink will sen the page to it's own named window.

Using the parameters in my example, the pop-up window will be a fixed size, and have no status bar or toolbars. Here is a more complete list of parameters:

status The status bar at the bottom of the window.
toolbar The standard browser toolbar, with buttons such as Back and Forward.
location The Location entry field where you enter the URL.
menubar The menu bar of the window
directories The standard browser directory buttons, such as What's New and What's Cool
resizable Allow/Disallow the user to resize the window.
scrollbars Enable the scrollbars if the document is bigger than the window
height Specifies the height of the window in pixels. (example: height='350')
width Specifies the width of the window in pixels.

a: Once Javascript creates the window, it assigns it to the Javascript object (in the example it's named "a").

a.focus(): If the user clicks the link on the main page again after the window was initially created, the main page may cover the pop up. This line says that whenever we pop or reload this window's URL, we'll set focus on it.

return false: It's a function. We're returning false. Bear with me, I'll explain why in a moment.

Now we'll look at the hyperlink. It's a nearly standard html construct with a few unfamiliar twists.

href="": This says to browse to noplace. We could have left this out, but then the link would not look like a link in the page. It would look like regular text. Normally passing in "" as the href would force a reload of the page we're already on, I'll show how to stop the page from reloading later.

onclick=: This is where we tell the link nto call our function. Now we could have just said onclick = "Pop('hrmlpage.htm')" but as it turns out the onclick event expects a return value. If that value is true, then the link exectues its default behavior and browses to the link in the href parameter, but if it recevices a false, it skips that part. We could have done this:


<a onclick="Pop('htmlpage.htm'); return false;" href="">Test the popup feature</a>

...and the reload of the main page would be suppressed. But in our case, since our function already returns a false (handy, huh?), we can use that value to tell onclick to stop the link from reloading. We need to tell the onclick call to accept the value of the function with the return keyword as shown in the original version of the html link.

Note that there is no reason the Pop function must be married to a hyperlink. It is possible (though annoying) to call it on page load, mouseover events, or any other browser event.

Monday, January 21, 2008

Why is EVERYTHING so Damned Hard?

Windows 2003 SBS ASP.NET 2008 Express SQL Server 2005 .net framework 3.5 (not beta)

So, I wanted to add a login page to my website and offer more content to logged-in users. I saw the login components and followed the tutorial to the letter. It works on my desktop perfectly. I can create logins and even the forgot my password crap works. I publish it to my website, and try to log in.

An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections.

Oh, shit! So I search the help (when am I going to learn?) and it tells me that all I have to do is open an Application that DOES NOT EXIST on my server, and grant THE INTERNET access to my DATABASE. I don't think so.

Please, if you know what is wrong, go to http://209software.com/Login.aspx and use the username "a" and the password "a". It's not a valid login, but it crashes every time trying to verify.

My web server, email server, and database server are all the same machine.

Here's what I want to know, and MSDN has squat on it.

  1. if I grant database access to the database, can people BROWSE my database over the web?
  2. What am I doing wrong? and how do I make it right?
  3. WHERE on the internet can you go if the Microsoft help is crap?

Ok, I got it. I downloaded something, but it wasn't SQL server 2005 express. Now, a mere 8 hours of downloading and installing later, it seems to work.

Contact Us

Name

Email *

Message *