How Did This Get Here, I Am Not Good With Computers

SharePoint | .NET | SQL | Web & Application Development

  Home  |   Contact  |   Syndication    |   Login
  11 Posts | 0 Stories | 17 Comments | 0 Trackbacks

News

All statements in this blog are my personal opinions and do not reflect the opinions of my employer.

Locations of visitors to this page

Add to Google Reader or Homepage

 Subscribe

Tag Cloud


Archives

Post Categories

Friday, November 13, 2009 #

By default, comments added in response to a post made in SharePoint Blog site are added by default. However there are instances where the blogger may want to have comments require approval before they are made publicly visible on the blog to others.

Comments are stored in a shared list within the Blog site, named Comments by default. They are categorized by post through the Post Title category. To require comment approval simple go into the list settings and goto "Versioning Settings". Under "Require content approval for submitted items?", select "Yes".

From now on when a user adds a comment they will first see a notification stating, "Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights." Once a comment has been added it will appear in the Comments list as Pending under the Approval Status column. Users that have at minimum Approver level access to the list will be able to approve or reject new comments.

If you want to be notified when a new comment has been added simply create an Alert under the Actions menu in the Comments list.

Monday, June 29, 2009 #

Hopefully this will help those of you who are running Windows Server 2008 and are getting "Access Denied" errors when trying to run any command in STSADM.

  • Make sure you're running the command prompt as an administrator (Right click command prompt in the start menu and select "Run as Administrator..."
  • Make sure the username you're running under is set as farm administrator as well as a local administrator on the server.
  • Make sure User Account Control is switched off (Control Panel > User Accounts). This is only really necessary if the above didn't work.
There was also a bug in older builds of MOSS 2007 (and possibly WSS 3.0?) that under specific conditions would cause Access Denied errors when running certain STSADM operation such as "import". These can be fixed by patching to SP2.

Friday, May 01, 2009 #

Was trying to export a site in WSS3.0 using the following command:
stsadm.exe -o export -url http://blah/blah -filename BlahBackup -includeusersecurity
Which promptly spit this out:
Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
This seems to be a fairly generic error, I was finding causes ranging from SQL Log file size to threading conflicts. The most common solution was to shrink the SQL log size of the content database of the site you're exporting. In my case this wasn't the cause of the error, instead what solved it was running the above command as a user who has DB_owner permissions to the content database.

Thursday, April 23, 2009 #

I've been messing around with Web Setup Projects in Visual Studio 2008 and have been using them to deploy an ASP application I've been working on. One thing I've learned is that Web Setup is very temperamental as far as how your development environment is setup. I've had to do everything from computer restarts to registry hacks to get my Projects to build, and thought I had finally nailed down all the issues until I had to redeploy my application today.

Upon building the Web Setup project I would get the "Build Failed" message along with no errors. Puzzled, I enabled detailed build logging in Visual Studio's options. And still, no errors.

As developers we've all gone through the process of problem solving. You start trying reasonable solutions that seem logically correlated to the issue at hand, and failing that slowly devolve into more obscure and senseless solutions that aren't even remotely related to what you're trying to fix. And this is precisely what happened.

What fixed my problem? Instead of opening my solution from the "Recent Projects" menu in the Visual Studio Start Page, I opened the solution through File > Open > Web Site...

Like I said, a senseless solution to a problem that should have never existed in the first place.

Wednesday, April 22, 2009 #

I ran into a situation where I was storing files in a database as a binary field. Some of these files were in HTML format and I wanted to dynamically display them inside of some ASP pages I was developing. After a bit of research I was finding a lot of other solutions people were using involved timestamp conversions which were not ASCII based like HTML. The following code will convert your binary object into ASCII and display it as it was originally uploaded.
byte[] myByteArray = myBinaryObj.ToArray();
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
string result = enc.GetString(myByteArray);

Wednesday, December 05, 2007 #

Whether you do web design or desktop application development, you're eventually going to need to include icons in your interface. Not all software developers are handy with image editing software, we can use it, like most people know how to use a paint brush, it's just that we have trouble using the tool to make something that would meet our users expectations. Luckily there are a lot of free resources out there that provide premade icons created by people who have artistic talent.

Icon Finder - Provides a Google like image search that only returns icons
Tango Desktop Project - A pack of icons available in every format and resolution you would ever need, licensed under GPL.
Famfamfam - A collection of icons with a simple and minimalistic style to them. There's also another pack in the same style available here.
Pixel Resort - Fairly new site, with a rapidly growing collection of icons.
Deviant Art - Probably one of the largest collections available, however it's really hit or miss, you can find some really nice sets if you can spare the time.

It's very likely you will find an icon that you like but isn't provided in the size or format you're looking for. In this case I recommend downloading Paint.NET which is a free image editing program that has excellent plugin support. If you're working on a desktop application and require icons in .ICO format you can download the ICO plugin for Paint.NET here.

I guess now would also be a good time to talk about what image format to use for you icons. The best format for most applications is PNG. It's small, no visible compression artifacts and supports alpha transparency. Applications built in Visual Studio support PNG icons along with transparency as do all modern browsers. As is usually the problem, Internet Explorer is the black sheep of the crowd and needs special attention when it comes to PNGs. There are still quite a few people using IE6 which does support PNGs but not PNG transparency. There is a solution to this using javascript within your CSS file to load the appropriate libraries to handle the transparency, however there are some major drawbacks to doing this as discussed here. IE7 introduces PNG transparency support, however still has the problem of incorrectly rendering colors in PNG files, seemingly oversaturating them. The next alternative is the GIF format, which also doesn't have visible compression artifacts and allows for simple non-alpha transparency. Avoid using JPEGs whenever possible.

As far as what you should look for when choosing an icon, try to keep a consistent theme amongst your application, mixing icons from different collections and artists can give the application a rough and inconsistent feel. Apple has an article aimed at developers outlining their guidelines for icon selection and placement. While some of it is Mac specific, many ideas can be related to all applications regardless of platform or OS. Here are some highlights from the article:
  • The icon should contain a tool that communicates the type of task the application allows the user to accomplish. The Preview icon, for example, uses a magnification tool to help convey that the application can be used to view pictures. If you include a supportive tool element, it should closely relate to the base object that it rests upon.
  • Some applications that represent objects, such as QuickTime Player and Calculator, are most easily recognized by the objects themselves. When creating icons for such applications, it’s more aesthetically pleasing to create a simplified, idealized representation of the object, instead of using an actual screen shot of the software. Re-creating the object is particularly important when users could confuse the icon with the actual interface.
  • Because utility applications are normally focused on a narrow set of tasks, it’s best to keep the number of elements in the icon to a minimum. The focus should be a single object that represents what the utility does.
  • The primary purpose of a toolbar is to provide users with easy access to frequently used commands. Although toolbar icons should conserve screen real estate they should be inviting and easy to identify. Ideally, each toolbar icon should represent a unique object or action that is directly related to the command it represents. A toolbar can also contain icons that represent recognizable interface elements from elsewhere in the system when they make sense in the context of the application. If you choose to include an icon such as an Info button, be sure to preserve its meaning. Users expect such icons to mean the same thing in every context, so you should not redefine them when you use them in your toolbar.
  • Do not use a system icon, such as the yellow caution icon, in your toolbar. A system icon provides important information to the user in a specific context, such as in an alert window; using it in a toolbar blurs its meaning and dilutes it effectiveness in the system.
  • Making each toolbar icon distinct helps the user associate it with its purpose and locate it quickly. Variations in shape, color, and image all help to differentiate one toolbar icon from another. At the same time, however, an application's toolbar icons should harmonize together as much as possible in their perspective, use of color, size, and visual weight.
  • Creating a family of visually related toolbar icons can strengthen the user's perception of your application as being well-integrated and well-designed. One way to do this is to start with a consistent theme for the style and appearance of the icons, then introduce variations when it makes sense.

Friday, November 30, 2007 #

By default, the search service is disabled in WSS 3.0. In order to enable it, goto your SharePoint Central Administration page and under the Operations tab, goto the "Services on the Server" list and click on WSS Search.
  • Service Account - You cannot use any built in accounts when specifiying the Service Account, however you can use local accounts. One account you can choose to use is the default Administrator account on your server, "myserver\Administrator".
  • Content Access Account - Use an account that has full read access to your SharePoint Content Databases. As a security precaution, try not to use an account that has write permissions on the database. For example: "mydomain\sqlserveruser".
  • Search Database - In most cases the default settings will work, change them as required.
  • Indexing Schedule - No new files will be searchable until they are indexed, depending on the load you wish to put on the server you can set this to be done as often as you want.
Upon submitting the form, the search service should start and begin indexing the content in your SharePoint site. Now would be a good time to install the Adobe IFilter to allow your search service be able to index PDF files, the earlier you install it the better, since it will only recognize PDF files added after the addon was installed.



Wednesday, November 28, 2007 #

I'm sure it has happened to all of us. You're using a new application, and you know what you want to do, but have trouble finding which button or window lets you do it. You probably start by going through the drop down menus one by one, scanning through the options for something that is remotely related to what you want to do. Bingo, you find what you're looking for but the button is greyed out. You're then left guessing what you need to do to get that button to allow itself to be clicked. Maybe you need to select this item first? Or maybe have this option enabled? Perhaps you need to open a different file? 

Having the user go on a treasure hunt to unlock the functionality they want from the application wastes their time and is a bad design decision on the part of the developer. This is something that is all too common in applications today, and put simply is BAD BAD BAD.

Developers take for granted that if they want to disable a feature in a program they simply grey it out. And while it is effective in communicating that the feature is unavailable, it does nothing to tell the user why it's unavailable. You might say, "Well maybe they should RTFM before they used my application!". And while that would be a fair argument 10-20 years ago, today it's not a valid excuse. Users today don't expect to read a manual before using an application, and rather expect the developer to do a good job designing the interface to make it intuitive and easy to use on the first go. When you buy an iPod, do you get a 100 page manual outlining how to use it? No, you get a tiny pamphlet that pretty much tells you to download iTunes, plug it into your computer and have at it. That's because Apple designed the interface to behave intuitively with the user's initial expectations of how the product should work, and considering their success they're on the right track.

So what better way is there to do this? Simple, rather than greying out the button, have it trigger a message box that communicates to the user that first of all, the feature they are trying to use is currently unavailable, and second, what is it they need to do in order to make it available. From a coders perspective this isn't really anymore work. For example, suppose you have a delete button in your application. Rather than disabling the control when there is nothing selected to delete, which in C# is as simple as mycontrol.Enabled = False; replace that line with MessageBox.Show("You must first select an item from the list to delete.");. That wasn't so hard now was it.

Of course, this doesn't mean that greying out buttons is the wrong thing to do in all cases. There are functions that are so basic that they don't require justification as to why they are disabled. For example, greying out the save button if there are no changes to save is prefectly acceptable. Also, greying out the paste button because there's nothing in the clipboard to paste is also correct. These functions are universal to most applications and most users are expected to understand what they do.

Making the decision as to whether or not you should communicate with the user why something is disabled comes down to what you expect your users to know and find intuitive. In a professionally designed interface one of the first steps that are taken in the design process is evaluating the audience for your application. If you're designing an automated checkout system for WalMart, you would assume that some of your users may have never even touched a computer before, and therefore have the application hold their hand and guide them through the entire checkout process. On the other hand if you're building a tool meant to be used by other developers you would expect them to already understand a lot about how the application works, and would only make the user feel stupid by pointing out something that is already obvious to them.

The bottom line is, before you write the code to disable a button, ask yourself, "Will it be painfully obvious to the user why this button is disabled?". Of course it's obvious to you because you're the one designing the application, the challenge is to put yourself in someone elses shoes, and assume the things they expect from your application in order to answer this question correctly. Once you have the answer you will know whether to simply grey it out, or leave it enabled and communicate to the user why the action cannot be executed.

Monday, November 26, 2007 #

Suppose you want your users to submit a list of items through your web page. These items could be inputted through many means such as a text box, combobox, listbox, etc. There are many ghetto solutions you could use to implement this like comma delimited lists or multiple postbacks. There are however much more elegant, and suprisingly easier ways of doing this using javascript. As an example we will start with an input box with a link below it that allows you to spawn several more input boxes. In addition, each spawned input box comes with its own delete link, allowing the user to remove items if they choose to. Each input box is given a unique incremented ID that can be easily accessed later on through postback.

Here's the javascript that makes it work:
<script type="text/javascript" language="javascript">     
var software_number = 1;
function addSoftwareInput()
{
var d = document.createElement("div");
var l = document.createElement("a");
var software = document.createElement("input");
software.setAttribute("type", "text");
software.setAttribute("id", "software"+software_number);
software.setAttribute("name", "software"+software_number);
software.setAttribute("size", "50");
software.setAttribute("maxlength", "74");
l.setAttribute("href", "javascript:removeSoftwareInput('s"+software_number+"');");
d.setAttribute("id", "s"+software_number);

var image = document.createTextNode("Delete");
l.appendChild(image);


d.appendChild(software);
d.appendChild(l);

document.getElementById("moreSoftware").appendChild(d);
software_number++;
software.focus();
}

function removeSoftwareInput(i)
{
var elm = document.getElementById(i);
document.getElementById("moreSoftware").removeChild(elm);
}
</script>
And the tiny amount of html to get it to show up:
<input type="text" name="software0" id="software0" size="50" maxlength="74" />                
<div id="moreSoftware"></div> <div id="moreSoftwareLink" style="display:block;"><a href="javascript:addSoftwareInput();">Add Another Item</a></div>
You can paste the above HTML and javascript into your own webpage to see it in action.

In some languages such as PHP, accessing these dynamically created elements after postback isn't an issue, it's a simple matter of using a for loop to iterate through each element. However this becomes a challenge if you're using ASP.NET. The problem is that these new elements are created on the client side, and once submitted, the server no longer sees them. The workaround is to use javascript to collect the contents of each element and stuff them into a hidden element in a delimited format. In the case of ASP.NET this hidden element would have to be declared within the page that is originally sent to the client. Then on postback we can collect the contents of this single element, break up each list item by the delimiter and deal with them as we normally would. First we create our hidden attribute to dump our item contents on submit:
<input id="ninjainput" type="hidden" name="ninjainput" />
We'll call it "ninjainput", because it's stealthy and mysterious, like a ninja. Next, we'll insert an additional javascript function that will populate our ninjainput when the user submits the page.
function populateStaticInput()
{
var n = document.getElementById("ninjainput");
var allsoftware = "";
for( var i = 0; i < software_number; i++)
{
var currentele = document.getElementById("software"+i);
if(currentele != null)
{
if(currentele.value.length > 0)
{
if(currentele.value.length > 74)
currentele.value = currentele.value.substring(0, 74);
allsoftware = allsoftware + "~<>~" + currentele.value;
}
}
}
n.value = allsoftware;
}
Notice that we are delimiting each item with a "~<>~". Make sure to add this attribute to your form tag: onsubmit="javascript:populateStaticInput();" This way the javascript will run and populate our ninjainput control before the page is sent to the server. Lastly, we will need a function (the example below is in C#) that will cut up the submitted list of items into a usable format, in this case an array of strings.
public string[] GetAllSoftwareInList(string rawsoftlist)
{
string[] asoft = rawsoftlist.Split("~<>~".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
return asoft;
}
And there you have it, the user doesn't have to endure multiple postbacks or keep track of a comma delimited list. It's presented in an organized and intuitive manner to the user and not too painful to implement for the developer.

Friday, November 23, 2007 #

When developing an application that uses a SQL Server Compact Edition database, you may run into a problem getting your application to build if you frequently compile it to test changes. Specifically the following error:
Problem generating manifest. The process cannot access the file 'C:\...\mydb.sdf' because it is being used by another process.
The problem is that your application didn't properly release its lock on the SQLCE database file the last time you ran it. I find this especially happens when you're debugging and hit an unhandled exception. Since your application runs as a child of the devenv.exe (Visual Studio) process, closing and reopening Visual Studio will release the lock on the SDF file and allow you to successfully compile again. Obviously, restarting Visual Studio everytime you want to test your application isn't very convenient.

There is an easier solution to this problem. You'll need to download Process Explorer, a free utility provided by Microsoft. According to the website, "Process Explorer shows you information about which handles and DLLs processes have opened or loaded". This is precisely what we need to release the SDF file that Visual Studio has taken hostage.

So open up Process Explorer, and using the "Find Handle or DLL..." feature search for "sdf". You may end up with several results, but what you're looking for is the SDF that you use in your application. Once you find it, double click it. The file will then appear highlighted on the bottom half of the window, right click it and select "Close Handle". The lock on the file will be destroyed, allowing you to successfully build your application without getting manifest generation errors.