Wednesday, November 28, 2007

Microsoft Report Viewer 2008

If you want to use the Report Viewer that comes with VS 2008 you need this version 9 ReportViewer.exe installed on the server.

Note: you need to install .NET 3.5 first.

Download details: Microsoft Report Viewer Redistributable 2008

Monday, November 26, 2007

Visual Studio 2008

Installed Visual Studio 2008. 3.3GB download for the Pro version. Why so big? got me.
Overall, very impressed. The ListView control looks nice. "A repeater on speed."

Monday, November 12, 2007

IE7

Why can't IE7 remember what tab I was looking at last when I remove a tab!?! Firefox can!

Monday, November 5, 2007

Comcast Violates Net Neutrality. File Your Own FCC Complaint!

Yes, this is a blatant solicitation get people to sign this complaint, but Comcast deserves it and Net Neutraility is being violated! ....Today, Free Press filed a legal complaint demanding that the FCC take action to protect the free flow of information on the Internet. By joining our complaint, you can help stop Comcast and other gatekeepers.

read more | digg story

Friday, November 2, 2007

Deploying Reports and ReportViewer Controls

If you get this error:
"Could not load file or assembly 'Microsoft.ReportViewer.WebForms, Version=8.0.0.0,"

You need to run this file on the server:
The ReportViewer control redistributable is a self-extracting file named ReportViewer.exe that includes an .msi and other files. You can find ReportViewer.exe at the following location: C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\ReportViewer\ReportViewer.exe.

Found the solution here:
Deploying Reports and ReportViewer Controls

SQL Server Reporting Services number of rows per page

Set a number of rows per page with the grouping trick:

Go to Table Properties - GroupsAdd a Row Group with the following function: =Ceiling(RowNumber(Nothing)/30)Make sure "page break at end" is checkedNow you have a set number of rows and with that a set vertical size(assuming text does not wrap).Make the control a little wider then needed and you should not have scrollbars (most of the time).


Found the code here:
SQL Server reportingsvcs ReportViewer control always shows scrollbars

Thursday, November 1, 2007

SQL Server Reporting Services RunningValue in a chart - scope issues

Using SQL 2005 and Visual Studio 2005 I wanted to show a cummulative series in a chart, plotted as a line. I had to add a "fake" series grouping in order to get it to work.

Found the solution here:

sqlserver reportingsvcs RunningValue in a chart - scope issues

Tuesday, October 2, 2007

DateTime Parse and CultureInfo problem.

Show US formatted dates in a different culture:

string dt = "1/31/2004";
CultureInfo nfo = new CultureInfo("en-US");
DateTime date = DateTime.Parse(dt, nfo);

CultureInfo nfo2 = new CultureInfo("en-GB");
Console.WriteLine(date.ToString(nfo2));

Found the code here.

Tuesday, September 25, 2007

24/7

Do advertisers really need to say "and you can shop online 24/7". It's 2007, I think everyone is well aware that websites are available ALL THE TIME.

Tuesday, September 18, 2007

Tuesday, September 11, 2007

Comcast must die.

Yet another story on how Comcast screwed one of their customers. They're Craptastic!

read more | digg story

Monday, September 10, 2007

System.Net.WebClient

I needed a way to grab some content from a remote site. The following code worked the best. You may not need to specify a proxy as I have.

System.Net.WebClient wc = new System.Net.WebClient();
 
string proxyURL = ConfigurationManager.AppSettings["ProxyURL"];
string proxyCredUserName = ConfigurationManager.AppSettings["ProxyUserName"];
string proxyCredPassword = ConfigurationManager.AppSettings["ProxyPassword"];
 
System.Net.WebProxy proxy = new System.Net.WebProxy(proxyURL);
System.Net.NetworkCredential cred = new System.Net.NetworkCredential(proxyCredUserName, proxyCredPassword, domain);
 
proxy.UseDefaultCredentials = true;
proxy.Credentials = cred;
wc.Proxy = proxy;
 
chartImage = wc.DownloadData(chartImageURL);

Monday, August 27, 2007

Microsoft SQL Reporting Services and Visual Studio 2005

If you want to be able to create Report Projects for SQL Reporting Services with Visual Studio 2005 you have to install SQL 2005, I did the Standard install, and make sure you select the "Business Intelligence" items. Wait forever.......and when the install is finally done you will get a option for "Report Server Project" when you select "New Project" in Visual Studio 2005.

Thursday, August 23, 2007

Seamless inline text editing with ASP.NET AJAX | Encosia

I've seen this done Google calendar and think it's a nice way to have the same page used as display and edit. The author of this blog does an awesome job of explaining each step.

Seamless inline text editing with ASP.NET AJAX Encosia

Tuesday, August 21, 2007

SAP MDM COM API SP5

I've noticed that the console now seems to show ALL com api connections in the Logins section. Apparently MDM COM API creates a connection for the application and another for the trace. I'm not sure if this is true but I've never saw it before moving to SP5.

Thursday, August 16, 2007

SQL Reporting Services

I had a report that looked great in the browser but showed this error when exported to Excel:
"Subreports within table/matrix cells are ignored."

It's a limitation with the software. I removed the table and put my Fields and sub reports in a List control. I set the datasource and grouping properties for the List control and everything works fine now.

Thursday, August 9, 2007

SAP MDM COM API Get Attribute By Category ID

public static DataTable GetByCategoryID(int attributeID, int categoryID, XCATCOMLib.Catalog catalog)
{
// There are 3 types of attributes:
// Feature - text values;
// Characteristic - numeric values;
// Coupled - coupled numeric values.

DataRow row = null;
DataTable dt = new DataTable();
dt.Columns.Add("AttributeID");
dt.Columns.Add("AttributeValue");
dt.Columns.Add("AttributeCoupleValue");
dt.Columns.Add("AttributeDisplayValue");
dt.Columns.Add("AttributeRating");
dt.Columns.Add("ShowAllFlag");
dt.Columns.Add("AttributePriority");
dt.Columns.Add("AttributeUnitID");
dt.Columns.Add("AttributeCoupleUnitID");

XCATCOMLib.Attribute prodAttribute = catalog.GetAttribute(CATEGORY_TABLE, attributeID);
XCATCOMLib.Search search = new XCATCOMLib.SearchClass();
XCATCOMLib.TaxonomyLookupParameter param = search.Parameters.NewTaxonomyLookupParameter(PRODUCT_TABLE, CATEGORY_FIELD);
param.NodeID = categoryID;


XCATCOMLib.FreeFormTableParameter tableParam = search.Parameters.NewFreeFormParameter(PRODUCT_TABLE);
XCATCOMLib.FeatureParameter featureParam = null;


int attribType = prodAttribute.Type;
string attribDefinition = prodAttribute.Definition;
byte attribPriority = prodAttribute.Priority;

if (attribType == 0) //xcFeatureValueType
{
XCATCOMLib.FeatureValues fvs = catalog.GetLimitedFeatureValues(search, CATEGORY_TABLE, attributeID);
foreach (FeatureValue fv in fvs)
{
row = dt.NewRow();
row["AttributeValue"] = fv.ID;
row["AttributeID"] = attributeID;
row["AttributeDisplayValue"] = fv.Value;
row["AttributeRating"] = 0;
row["ShowAllFlag"] = false;
row["AttributePriority"] = attribPriority;
row["AttributeUnitID"] = "";
row["AttributeCoupleUnitID"] = "";
dt.Rows.Add(row);
}
}
else if ((attribType & 0xFF) > 0) //xcCharacteristicValueType
{
string attribName = Helper.FormatAttributeName(prodAttribute.Name);
string attribAlias = prodAttribute.Alias;

int[] gRatingArray = new int[5];
gRatingArray[0] = 8;//"xcNominalRating";
gRatingArray[1] = 1;//"xcMinimumRating";
gRatingArray[2] = 2;//"xcMaximumRating";
gRatingArray[3] = 16;//"xcAverageRating";
gRatingArray[4] = 4;//"xcTypicalRating";

int attribTypeInt = prodAttribute.Type;
for (int k = 0; k < gRatingArray.Length; k++)
{
int rating = gRatingArray[k];

if ((attribTypeInt & rating) == rating)
{
XCATCOMLib.CharacteristicValues cvs = catalog.GetLimitedCharacteristicValues(search, CATEGORY_TABLE, attributeID, (RatingEnum)rating);

foreach (CharacteristicValue cv in cvs)
{
row = dt.NewRow();
row["AttributeID"] = attributeID;
row["AttributeDisplayValue"] = cv.GetString(prodAttribute.DimensionID, prodAttribute.DecimalPlaces, prodAttribute.AllowFractions, cv.UnitID);;
row["AttributeValue"] = cv.Value;
row["AttributeCoupleValue"] = "";
row["AttributeRating"] = rating;
row["ShowAllFlag"] = false;
row["AttributePriority"] = attribPriority;
row["AttributeUnitID"] = cv.UnitID;
row["AttributeCoupleUnitID"] = "";
dt.Rows.Add(row);
}
}
}
}
else if (attribType == 0x8000) //xcCoupledValueType
{
XCATCOMLib.CoupledValues cpvs = catalog.GetLimitedCoupledValues(search, CATEGORY_TABLE, attributeID);
foreach (CoupledValue cpv in cpvs)
{
string primary;
string coupled;
primary = cpv.Primary.GetString(prodAttribute.DimensionID, prodAttribute.DecimalPlaces, prodAttribute.AllowFractions, cpv.Primary.UnitID);
coupled = cpv.Coupled.GetString(prodAttribute.CoupledDimensionID, prodAttribute.CoupledDecimalPlaces, prodAttribute.CoupledAllowFractions, cpv.Coupled.UnitID);

row = dt.NewRow();
row["AttributeDisplayValue"] = primary + " " + prodAttribute.CoupledDelimiter + " " + coupled;;
row["AttributeValue"] = cpv.Primary.Value;
row["AttributeCoupleValue"] = cpv.Coupled.Value;
row["AttributeID"] = attributeID;
row["AttributeRating"] = 0;
row["ShowAllFlag"] = false;
row["AttributePriority"] = attribPriority;
row["AttributeUnitID"] = cpv.Primary.UnitID;
row["AttributeCoupleUnitID"] = cpv.Coupled.UnitID;
dt.Rows.Add(row);
}
}

return dt;
}

SAP MDM COM API SP5

MDM SP5 seems to be faster overall. A new field has been added in the console called "Code". This is really nice because now you can access fields using this Code name instead of the display Name.

There were a lot of places in where I had to change .Name to .Code, but after that the upgrade went smoothly.

Friday, August 3, 2007

Scrollovers - A New Way of Linking

I like the idea. Too many on a page might be overkill though.

Scrollovers - A New Way of Linking

Tuesday, July 24, 2007

2010, a "Windows 7" software subscription odyssey

Microsoft has again confirmed that the "big release" approach to software development is alive and well at Microsoft. Ballmer said as much earlier this year in advance of the retail Vista launch, but the company is reiterating the point now as it ramps up preparation for the next version of Windows and a renewed push for software subscriptions.

read more | digg story

Thursday, July 19, 2007

Send Web User Control as Email

I often have to setup an application to auto-send emails. I use a user control as the body of the email to save time formatting the HTML.

private string getSupervisorEmailContent()
{
    string content;
 
    // create and populate an instance of a ContentControl user control
    EmailSupervisor cc = (EmailSupervisor)this.LoadControl("EmailSupervisor.ascx");
    cc.EmployeeName = this.lblEmployeeName.Text;
    cc.SystemLink = "http://" + HttpContext.Current.Request.Url.Host + "/TechLadder";
 
    // render the output of the user control to a string, for use by the email message body
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    System.IO.StringWriter sw = new System.IO.StringWriter(sb);
    System.Web.UI.HtmlTextWriter htmltw = new System.Web.UI.HtmlTextWriter(sw);
    cc.RenderControl(htmltw);
    content = sb.ToString();
 
    return content;
}
 
private void SendSupervisorEmail(string email)
{
    try
    {
        MailAddress from = new MailAddress("no-reply@andrew.com");
        MailAddress to = new MailAddress(email);
        MailMessage Message = new MailMessage(from, to);
        Message.IsBodyHtml = true;
        Message.Subject = "System Engineering Technical Ladder";
        string superMsg = getSupervisorEmailContent();
        Message.Body = superMsg;
 
        SmtpClient client = new SmtpClient(ConfigurationManager.AppSettings["Andrew:MailServer"]);
        client.Send(Message);
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Tuesday, July 17, 2007

SAP MDM COM API

For more than a year I’ve been using the SAP MDM (Master Data Management) COM API with .NET 1.1. Getting started was frustrating. There isn’t a lot of code samples out there.
Here is a simple function to get the product record by product ID.

public static XCATCOMLib.ResultSet GetResultSet(int productID, XCATCOMLib.Catalog catalog)
{
XCATCOMLib.Search search = new XCATCOMLib.SearchClass();
XCATCOMLib.ResultSetDefinition productsRsDef = null;

// get references to tables
XCATCOMLib.Tables tables = catalog.Tables;
XCATCOMLib.Table prodTable = tables.Item(PRODUCT_TABLE);

// products
productsRsDef = new XCATCOMLib.ResultSetDefinitionClass();
productsRsDef.Table = prodTable.Name;

//get the column names of the product table
for (int j = 0; j < prodTable.Fields.Count; j++)
{
productsRsDef.Fields.Add(prodTable.Fields.Item(j));
}

XCATCOMLib.TableParameter lp = search.Parameters.NewTableParameter(PRODUCT_TABLE);
lp.RecordIDs.Add(productID);

ResultSet rs = catalog.GetResultSet(search, productsRsDef, prodTable.Fields.Item(0).Name, true, 0);

return rs;
}

Retrieve Microsoft Exchange FreeBusy data

I wanted to show an exchange users calendar for the current day. There is a command you can use with Microsoft Outlook web access. At first I thought I could just call this command, parse the XML and display a table from 8am to 5pm showing out of office, in a meeting, etc..
What I didn’t realize is that you will always get back null unless you run the command on the exchange server. Microsft actually explains that you should use the command to make a web service.

You can also use CDOEX, (Collaboration Data Objects for Exchange), to retrieve the data. Again, this must be run on the exchange server. You’d have to find the cdoex.dll and regsvr32 it locally to add it to Visual Studio. You can find the dll on the exchange server or search the web. That code looks like this:

string freebusy = “EMPTY”;
int Interval = 30;
DateTime dtStartDate = DateTime.Parse(“2/8/2007 1:00:00 AM”);
DateTime dtEndDate = DateTime.Parse(“2/8/2007 11:00:00 PM”);


CDO.Addressee iAddr = new CDO.Addressee();
ActiveDs.ADSystemInfo Info = new ActiveDs.ADSystemInfo();

iAddr.EmailAddress = “example@example.com”;
if (!(iAddr.CheckName(“LDAP://” + Info.DomainDNSName, “”, “”)))
throw new System.Exception(“Error occured!”);

freebusy = iAddr.GetFreeBusy(dtStartDate, dtEndDate, 30, “”, “”, “”, “”);

Change Gridview row color

One way to change the entire row color of a GridView is to do it during RowDataBound(). If a flag returns true from the database I wanted to make that entire row red. Here is how I did that:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView test = (System.Data.DataRowView)e.Row.DataItem;
bool actionPlanExists = SqlConvert.ToBoolean(test.Row[“ActionPlanExists”]);
if (actionPlanExists == true)
{
e.Row.BackColor = System.Drawing.Color.Red;
e.Row.ForeColor = System.Drawing.Color.White;
}
}
}

.NET Localization

Here is code to offer a dropdownlist so visitors can change the language.

– Language –
English
中文版本 - Chinese
Ceština - Czech
Francois - French
Deutsch - German
Italiono - Italian
Español - Spanish
Português - Portuguese

protected void ddlLanguage_SelectedIndexChanged(object sender, EventArgs e)
{
//store the selected language in a cookie
}
protected override void InitializeCulture()
{
string lang = string.Empty;
HttpCookie cookie = System.Web.HttpContext.Current.Request.Cookies[“MyAPP”];

if (cookie != null)
{
try
{
lang = cookie[“Language”];
}
catch
{ }
}

if ((lang != null) && (lang != string.Empty))
{
String selectedLanguage = lang;

if ((selectedLanguage != null) && (selectedLanguage != “”))
{
UICulture = selectedLanguage;
Culture = selectedLanguage;

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(selectedLanguage);
}
base.InitializeCulture();
}
}

MDM Get Attributes

I needed a way to get all the attributes for a repository in MDM. I did that with the MDM COM API like this:


this.catalog = Helper.GetCatalog();


DataTable dt = new DataTable();
dt.Columns.Add(”Name”);
dt.Columns.Add(”ID”);
XCATCOMLib.Attributes allAttributes = new XCATCOMLib.AttributesClass();
allAttributes = catalog.GetAttributes(CATEGORY_TABLE, 0, false);


foreach(XCATCOMLib.Attribute attrib in allAttributes)
{

DataRow row = dt.NewRow();
row[”Name”] = attrib.Name;
row[”ID”] = attrib.ID;
dt.Rows.Add(row);

}

this.dgAttributes.DataSource = dt;

this.dgAttributes.DataBind();

MDM Multiple Languages

MDM has great support for multiple languages. You can login to their GUI client (Data Manager) with your desired language. I found out that when you use the MDM COM API with multiple languages to get images you have to use their enumerations.

You can’t pass in “Original”, you must pass in XCATCOMLib.ImageVariantTypeEnum.xcOriginalType
I also had to get the “Images” tableID. Otherwise the Secondary languages will not retrieve an image.

Here’s a function to get an image:

public static string GetImage(XCATCOMLib.Fields objFields, XCATCOMLib.Catalog catalog, ImageVariantTypeEnum variantType)
{
string imgURL;
System.Object[] imgID = (System.Object[])objFields.Item(”Images”).Value;
int imagesTable = objFields.Item(”Images”).LookupTableID;
int webimgID = int.Parse(imgID.GetValue(0).ToString());

CachedImageInfo imgInfo = catalog.GetCachedImageInfo(imagesTable, webimgID, variantType);
string imageCached = imgInfo.CachedPath.Replace(”\\”,”/”);
imgURL = ConfigurationSettings.AppSettings[”ImagesCacheFolder”] + “/” + imageCached;

return imgURL;
}