Archive

Archive for the ‘Sharepoint’ Category

Dynamic Images from Web Parts

September 27th, 2006 No comments

What are you mad !! You can’t do it, how on earth are you going to suddenly be called again as an image and write binary data out.  

If you’ve read previous posts you will see that I have been writing a web part that gets SiteUsageData and displays it.  It uses some nasty COM+.  I got to thinking how on earth am I going to graph this dynamic data that changes per site?

HttpHandlers – for a bit more info on HttpHandlers see here on Scott Hanselman’s blog.

Now your up to speed on them, how can we use them with a part. 

First we have to spit out the IMG tag in your render section.

textWriter(“<img src=’_layouts/MyWebPartImage.ashx/’>”);

Of course that on its own does nothing, but note the url “_layouts”, not “/_layouts” this is very important as your part will run in the Site context of “/” if you do, instead of the current site.

Second you need to register this HttpHandler in web.config

<add verb=”GET” path=”MyWebPartImage.ashx” type=”Binaryjam.MyWebPartNs.MyWebPart, Binaryjam.MyWebPartNs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5**************d” />

Replace those details with your own namespace, typename, public key.  Ahh Did I say you need to GAC this part.  I haven’t experimented with not GACing this feel free to but to be sure GAC IT.

Third add the IHttpHAndler interface to your web part class

public class MyWebPart: WebPart, IHttpHandler

Nearly there now add your Interface methods, remember Scott’s article ? Here is a simple example of this:

public void ProcessRequest(HttpContext context)
{
    HttpResponse response=context.Response;
    HttpRequest request=context.Request;
    response.ContentType=”image/jpeg”

    Graphics g=null;
    System.Drawing.Image image=null;
    image=new Bitmap(Width,Height,PixelFormat.Format32bppArgb);
    g=Graphics.FromImage(image);
    g.FillRectangle(new SolidBrush
            (Color.White),0,0,image.Width,image.Height);
    g.DrawString(“YooHoo”,new Font(“Verdana”, 10.0f),
             new SolidBrush(Color.Black),0,0);
    image.Save(response.OutputStream,ImageFormat.Jpeg);

}

public bool IsReusable
{
  get
  {
    return true;
  }
}

These pieces of code give you the basics to dynamically generate an image from a web part.  Now because the webpart is being created again in the context of the site its running in in theory its Properties are populated, however you would need to check this.  For my use I only needed to now the site Context, I could then use the Sharepoint API and the site context

SPWeb thisWeb = SPControl.GetContextWeb(Context);

To get the data I need.  You could use the API to access list information in a site and graph that too.

And no I don’t have a full code example, my graphics code is too embarrassing.
:-)

 

Its here I might point out that doing this might be a really bad idea, lets face it we don’t know what’s happening behind the scenes, but lets have a guess.  You have already hit this page once to display the web part. To display the image the site is visited a second time, admittedly not the rendered page but the site all the same.  Now what could be happening here is that the Sharepoint httphandlers, because remember its not the aspx ones running, initialise loads of Sharepoint stuff.  Then you create a webpart, now either the Sharepoint context exists already of the webpart creates it, considering that on a page could be multiple web parts are they all creating contexts ? or calling a static to get it ?  Anything could be happening here.   On the other hand is it as bad as hosting an image held in a site list in a CWP part on your site ?  Probably very similar.

If there are any Sharepoint under-the-covers experts who know what’s happening, let me know please.

tags: sharepoint+webparts, sharepoint, GetUsageData, evil+voodoo+in+sharepoint

Categories: development, Sharepoint Tags:

Installing the COM+ .NET component

September 22nd, 2006 No comments

A couple of posts ago I talked about a GetUsageData webpart and how to access the data when not a site admin by using COM+ to retrieve the data.

But of course this needs to be installed.  Luckily for me we have a MSI library that Dan developed, which does all the sharepoint web part installation, as well as a host of other web based installation tasks that do not come out of the box with MS’s installation project.  But this only helps me with the webpart.

The earlier articles mention using Regsvsc to register the COM+ component or to allow lazy regristation.  Whilst manually registering is certainly better than lazy its still yet one more task that could be done as an MSI.

Here is a great article about registering COM+ components from start to finish with multiple methods. There is a section on writing an MSI installer class to acheive this using the .NET Library RegistrationHelper, it won’t take a genious for you to figure out how you can extend this to install your web part.

Note specifically the custom actions bit,  also look at custom action data as this is how you can get data into the MSI from the command line enabling unattended installations.  Also you can create a form in your dll to capture data in interactive mode to be fed into your installer (check /SILENT).

But is it enough, for me no.  RegistrationHelper does not let you configure the admin user details.  To achieve this you can do more.  First capture those details either from CustomActionData or your form. Then use techniques I found here

For those who hate vb.net here is some c#

Set a reference to COMAdmin library (its a COM one not .NET),  Have already registered the component in COM+ and stored the Package name in appID

catalog=new COMAdmin.COMAdminCatalog();
applications = (COMAdmin.COMAdminCatalogCollection)catalog.GetCollection(“Applications”);
applications.Populate();

foreach (COMAdmin.COMAdminCatalogObject applicationItem in applications)
{
    string s=applicationItem.Name.ToString() ;
    if (s==appID)
    {
        application=applicationItem;
        bGotOne=true;
        break;
    }
}

if (!bGotOne) return//I’m so slack !!

if (login.Length>0 && loginpwd.Length>0)
{
    application.set_Value(“Identity”, login);
    application.set_Value(“Password”,loginpwd);

    applications.SaveChanges();
}

Remember to Have GAC’d your component in code, and remember to uninstall all this too in the correct order.

Full list of articles I used to get here

http://www.carlosag.net/Articles/configureComPlus.aspx
http://www.15seconds.com/issue/030501.htm
http://blog.u2u.info/DottextWeb/patrick/archive/2004/10/20/235.aspx
http://blogs.microsoft.fr/rlondner/articles/7089.aspx

tags: , , , ,

Categories: development, Sharepoint Tags:

Sharepoint GetUsageData In a WebPart

September 19th, 2006 4 comments

  So you want the world to see your sites Usage data, except you have a problem, access to the reports is only provided to the administrators of a site.  Well you could give everyone administrator rights and you could gnaw off your own foot but neither is a good idea the administration one less so.

So I know I’ll do this in a web part and just call some impersonation stuff, you know that WindowsImpersonationContext object will do fine. So you build a part, do the “Mike Yarwood” and whoooah now no one ‘cept you, can see your site.

So this is the point you get stuck, and think “google”.  After some searching I found Patrick Tisseghem’s blog with a post on this very subject.

First he solves your “Bang” no one see this, which could come in handy for Admin only web parts

SPControl.GetContextSite(HttpContext.Current).CatchAccessDeniedException = false;

But then comes up with good a old .NET running under COM+ example.  His example shows a webs.count usage, but UsageData works in the same way.

Another helpful article I found later in trying to get this mare to work ( I just love mixing Sharepoint, Gac, Com+  IISReset is your friend!!!)  was found here.  This article fills in some blanks about auto configuring the COM+ Application settings, What it doesn’t do is set the correct user, Make sure you go and set this else it will not work, make sure the user has sharepoint admin access to ALL areas, cos this is a web part anyone can use remember.

When using GetUsageData, remember that this information is gathered once a day so plenty of Caching opportunities here, don’t keep doing cross process communication as this has to be a Server component not a library one.

One thing that does puzzle me, is why dont my components spin in the Component Services tool when called ?

So Why ain’t I spinning then ? (and yes timeout of 3 minutes is set)

And one more thing, try at your own risk.  Im not saying it doesn’t work, just that you should investigate whats happening before you do it.

tags: , , ,

Categories: Sharepoint Tags:

Sharepoint "Hit Counter"

September 12th, 2006 No comments

I’ve been asked to look at doing a web part for this.  Now whilst I think that the old web odometer hit counters are a really bad Idea, that’s what’s required.  However considering how many times a web part could be called in just one page render, it would be daft to try and do it like this.

So I found this

site.GetUsageData(…)

Provided that you have turned on the Usage analysis processing it may be possible to get this information via a web part.

The original article that does this via another web is found here.

*Update* : More details on this

tags: ,

Categories: Sharepoint Tags:

Sharepoint List API, Slow ?

September 1st, 2006 6 comments

Just recently I’ve had the joy of creating a web part that reads a list.  It was decided the list data needed to be presented in a better way with the ability to page the data and drill down.

I created the part and it looked pretty good, I thought, then came the time to test it.  It worked fine for me but that was before I populated it with 100 items with 5 items it was fine, of course.  Bugger.

Well I spent a fair few hours ripping my code apart, its strange when you optimise code as you look at it with different eyes and what seemed good sensible ideas, became glaring monstrosities.  In a few dev cycles I brought the times down from 16 seconds to render the part to 10, to 4.

But four seconds!!!  Thats rubbish.

I had object cached almost everything in sight, I’d removed loads of control creates and just raw HTML’d the lot I got to the point I was checking every string concatenation was done efficiently.  I even tried to get DevPartner community edition to see where the bottlenecks where (this just did not work, great for windows apps, but could not get this working for sharepoint (if you have leave a clue)).

Luckily for me others in our team had come across slow list API before, and spent days figuring it out so I looked in their code and spotted one line of code they did that I didn’t, but that couldn’t be it surely.

I had been doing the equivalent to this.

SPList selectedList;
selectedList= currentSite.Lists["Locations"];

string Title=selectedList.Items["Title"].ToString();

Obivously I had more than just title to display and used the same technique all the way down. However by doing this

SPList selectedList;
SPListItemCollection myItems;
selectedList= currentSite.Lists["Locations"];
myItems=selectedList.Items;

string Title=myItems["Title"].ToString();

This gave HUGE performance increases. Apparently and I’ve yet to find the article myself, but the lads told me they read that unless you object cache the items collection it hits the DB but assigned to a local variable and it caches the data.  This would appear to be the case based on the speed increase I have seen here.

So next time your list access is slow  try the above.

tags: , , , ,

Categories: Sharepoint Tags: