Archive

Archive for the ‘ASP.NET’ Category

Sorting and Filtering Objects within Generic Lists

June 25th, 2017 Michael Bell No comments

I started working with Generics about 6 months ago. The main reason is because I just now started using custom objects for just about everything in my applications. It was a bit of a pain in the rear when I found out the GridView sort didn’t ‘just work’ when you bound it to a generic collection like the way it does when you bind it to a dataset. The other caveat I found was that it was more difficult to filter. I couldn’t just use DataViews or a Select on the table in the DataSet. I had to create some new functionality for filtering and sorting for generics. Here are my examples.

This first method takes a generic list as a parameter and passes the same list back, but sorted. Note that this requires the Comparison Generic Delegate listed down the page further. Substitute in your own custom object for my “ImageObject”:
// Pass in a generic list of objects (ImageObjects in my case) you want sorted, and by what property you want it sorted.
public List<ImageObject> sortImageList(List<ImageObject> ImageList, string sortExpression)
{
    SortExp = sortExpression;

    if (sortExpression != string.Empty)
    {
        Comparison<ImageObject> compare;
        compare = new Comparison<ImageObject>(CompareBy);
        ImageList.Sort(compare);
    }

    return ImageList;
}

This version does the same thing as the last, but, instead of passing in a List, it grabs one from the data access layer, sorts it, then returns it. Note that this requires the Comparison Generic Delegate listed down the page further. Substitute in your own custom object for my “ImageObject”:
public List<ImageObject> sortImageList(int OwnerID, UserData.ImageLookupType LookupType, bool sort, string sortExpression)
{
    List<ImageObject> list = _UserData.getImageList(OwnerID, LookupType);

    SortExp = sortExpression;

    if (sortExpression != string.Empty)
    {
        Comparison<ImageObject> compare;
        compare = new Comparison<ImageObject>(CompareBy);
        list.Sort(compare);
    }

    return list;
}

Here is the Comparison Generic Delegate that does our object comparison and bubbles them into order. Substitute your own objects’ property names:
private int CompareBy(ImageObject Image1, ImageObject Image2)
{
    int iRet = 0;
    switch (_SortExp)
    {
        case “Name”:
        case “Name ASC”:
            iRet = Image1.Name.CompareTo(Image2.Name);
            break;
        case “Name DESC”:
            iRet = Image2.Name.CompareTo(Image1.Name);
            break;
        case “DateUploaded”:
        case “DateUploaded ASC”:
            iRet = Image1.DateUploaded.CompareTo(Image2.DateUploaded);
            break;
        case “DateUploaded DESC”:
            iRet = Image2.DateUploaded.CompareTo(Image1.DateUploaded);
            break;
        case “Views”:
        case “Views ASC”:
            iRet = Image1.Views.CompareTo(Image2.Views);
            break;
        case “Views DESC”:
            iRet = Image2.Views.CompareTo(Image1.Views);
            break;
    }

    return iRet;
}

This leaves us with filtering. In this first method, you pass in a full list and return a single object based on the filter criteria:
public ImageObject FilterByImageID(List<ImageObject> ImageList, int ImageID)
{
    Predicate<ImageObject> filterByImageID;
    ImageIDFilter filter = new ImageIDFilter(ImageID);
    filterByImageID = new Predicate<ImageObject>(filter.FilterByImageID);
    return ImageList.Find(filterByImageID);
}

The ImageIDFilter is the name of teh class I created to do the actual
comparison of the object in the lists property to the criteria I’ve
passed in:
private class ImageIDFilter
{
    private int _ImageID;

    public bool FilterByImageID(ImageObject Image)
    {
        return (Image.ImageID == _ImageID);
    }

    public ImageIDFilter(int ImageID)
    {
        _ImageID = ImageID;
    }
}

There is also a shorthand version of this same method:
ImageObject io = myGenericList.Find(delegate(ImageObject image) { return image.Image == _ImageID; });

The latter would be much easier for simple filters, whereas the former best for more complex filtering.

Categories: ASP.NET, c# Tags:

JavaScript, JSON, WCF, and passing dates, oh my!!!!

June 25th, 2017 Michael Bell No comments

I spent more time than I will EVER admit trying to figure out what the heck was wrong with my code, passing a date created by the jQuery UI datepicker into my .NET WCF service. I tried tick conversions (which would wind up sending a date WCF didn’t understand). The only things I COULD get WCF to understand, read around the year 1970. So, with a bit of research, I woudn up with the following code to convert a javascript date to a format that WCF wants to see.

$.ajax({
     type: "POST",
     contentType: "application/json; charset=utf-8",
     url: "/WebServices/WebServiceHost.svc/scorePhotographer",
     data: '{"datevisited": "\\\/Date(' + Date.UTC(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate(), x.getUTCHours(), x.getUTCMinutes(), x.getUTCSeconds(), x.getUTCMilliseconds()) +
          (-x.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(x.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(x.getTimezoneOffset() / 60)) + '00' +
          ')\\\/" +
          '"}',
     dataType: "json",
     dataFilter: function(data, type) {
     var d = data.replace(/"\\\/(Date\(.*?\))\\\/"/gi, 'new $1');
     return d;
},
success: function (msg) {
     // blah
},
error: function (e) {
     //blah
}
});

Hope this helps someone!

Categories: AJAX, ASP.NET, WCF, jQuery Tags:

Automating SharePoint web.config Changes

June 25th, 2017 Michael Bell No comments

Here is my take on automating web.config changes in SharePoint 2007. In this example I make some changes so that I see detailed errors and stack traces on exceptions that are thrown within SharePoint. A few things I learned while playing around with this the first few times:

  • If you have mods going in in several places, or have lots of mods, complete them all and then do your Update() and ApplyWebConfigModifications(). If you do several saves, you will run into some strange looking problems during your deploys. It acts like there’s another package that didn’t get finished deploying and stop you.
  • Be mindful of the “Owner” property. It keeps track of who owns what modifications. It’s easy to wind up with orphans while you’re just learning how to do this, and you can hack up the web.config pretty good like that. If you end up fouling up your config settings like I did (Hey, I’m not an XPath guy!), check out Vincent Rothwell’s post on cleaning it up.
  • Brush up on XPath before you start executing this stuff.

Keep in mind that in this example I put the Update and Apply in the end just for the purpose of providing a complete example. In a real world scenario, you could use this method while you’re adding other modifications, but you wouldn’t want to save those mods until they are all added to the collection. 1 save per activation.

internal static void setErrorDetailSettings(SPWebApplication WebApp, string Owner, bool ShowErrors)
{

    SPWebApplication WebApp = siteCollection.WebApplication;
    SPServiceCollection services = WebApp.Farm.Services;
    SPWebApplicationCollection WebApps = services.GetValue<SPWebService>().WebApplications;

    string callStackValue = (ShowErrors) ? “true” : “false”;
    string customErroresValue = (ShowErrors) ? “Off” : “On”;

    SPWebConfigModification stackTraceModification =
        new SPWebConfigModification(“CallStack”, “configuration/SharePoint/SafeMode”);
    stackTraceModification.Value = callStackValue;
    stackTraceModification.Sequence = 1;
    stackTraceModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;
    WebApp.WebConfigModifications.Add(stackTraceModification);

    SPWebConfigModification customErrorsModification =
        new SPWebConfigModification(“mode”, “configuration/system.web/customErrors”);
    customErrorsModification.Value = customErroresValue;
    customErrorsModification.Sequence = 1;
    customErrorsModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;
    WebApp.WebConfigModifications.Add(customErrorsModification);

    WebApp.Update();
    WebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
}

Categories: ASP.NET, MOSS, SharePoint 2007, c# Tags:

“Column is constrained to be unique. Value is already present.” Error with in-memory table row inserts

June 25th, 2017 Michael Bell No comments

With my in-memory log-hit table I talked about in my last entry, I started getting these errors a few times a day, and it was enough to bomb the whole app:
Column ‘blahblah’ is constrained to be unique.  Value ‘-4862′ is already present.
Column ‘blahblah’ is constrained to be unique.  Value ‘-4847′ is already present.
Column ‘blahblah’ is constrained to be unique.  Value ‘-4768′ is already present.

Let me show you how the ‘blahblah’ column is built in the table construction:
DataColumn dc;

dc = new DataColumn(“HitID”, typeof(Int32));
dc.Unique = true;
dc.AutoIncrement = true;
dc.AutoIncrementSeed = -1;
dc.AutoIncrementStep = -1;
_MyTable.Columns.Add(dc);

So how in the world is this happening? Let me show the piece of code that was throwing the exception:
DataRow row = MemoryTables.HitList.NewRow();
row["FileID"] = Convert.ToInt32(context.Request.QueryString["fi"]);
row["FileName"] = fi.Name;
row["Username"] = _Username;
row["MemberID"] = _MemberID;
row["Success"] = true;
row["Bytes"] = fi.Length;
MemoryTables.HitList.Rows.Add(row);

Fairly straight forward.. right? With each hit to an image, this thing fires and inserts a new row into the in-memory table. About 20 rows get inserted a second. After much trial and error, I completely eliminated this problem by re-arranging a few lines of code. The new code reads:
DataRow row = MemoryTables.HitList.NewRow();
MemoryTables.HitList.Rows.Add(row);
row["FileID"] = Convert.ToInt32(context.Request.QueryString["fi"]);
row["FileName"] = fi.Name;
row["Username"] = _Username;
row["MemberID"] = _MemberID;
row["Success"] = true;
row["Bytes"] = fi.Length;

By creating a new row and adding it to the table before I populate it with any values, I eliminate my problem. I’d love to hear an explanation if anyone has one…

Categories: ASP.NET, c# Tags: