30 November, 2008

Copying an unseekable stream

I came across this issue the other day. I was trying to copy an image from a site into my SharePoint list. The issue was that the Stream that I was receiving was not seekable making it impossible to find out its size. After some awesome google skills and some help from my workmate we came up with a simple solution.

We copy the unseekable stream 64bytes at a time into a new stream making it seekable.

and TADA, this is what you end up with

private static void CopyUnseekableStream(Stream input, Stream output)
{
if (input == null) throw new ArgumentNullException("input");
if (output == null) throw new ArgumentNullException("output");
try
{
using (BinaryWriter bwWriter = new BinaryWriter(output))
using (BinaryReader brReader = new BinaryReader(input))
{
byte[] buf;
do
{
buf = brReader.ReadBytes(1024 * 64); // you can make this any size
bwWriter.Write(buf);
}
while (buf.Length > 0);
bwWriter.Close();
brReader.Close();
}
}
catch (Exception ex)
{

//need to catch errors
}
}
}

17 November, 2008

Virtual Earth Web Part for SharePoint Part 1

We all know that Microsoft have released new live BETA controls for the development community to use. I've been playing around with the Virtual Earth control and trying to get it to work within a Share Point web part.

I started this development using just a plain HTML page to see how the functionality works.
I've had a go at adding the control to the page and add/remove/move/load pins. Pins will be the most important part of your virtual earth. Whether you want to or not, users want to have the ability to plot destinations on the globe. There are many different reasons why a user would want to plot locations. To be honest I don't care why, as to HOW now that's what I want to discover.

We need to start this easy html page by referencing the control and adding the control to the page, and adding the required radio buttons that we will use to determine our users action. This is due to the fact that there is no Right click in web!

I start with a basic html page so that you can work out all the necessities for your JavaScript code. Since you can't really debug the js from your web part you will need to debug it in VS 2008 !

Let's begin.

1. We need to add all the required elements to the page. We need to reference the js control and from Microsoft.

<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>

now that we have referenced the controls we need to add all the required elements to the page. I will take you through everything that we are adding.

1. We need to add the Virtual Earth Control:

<div id='myMap' style='position:relative; width:400px; height:300px;'></div>

This will add a blank space to your page. This is where the map will load. Its nothing more than a div with some sizes.

In order to load the map we will need to add a button and we will load the map and some default pins on the button click.

<input id="getMap" type="button" value="Get Map" name="getMap" onclick='GetMap();loadPins();'/>

There are two main methods that we will create.

1.1 GetMap(); this will load up the map
1.2 loadPins(); this will load the default pins.

speaking of load pins, we will add some default pins to this page as follows:


<input type="hidden" id="VEpin_msftve_1000_200001" value="Default Description;-41.28854540914936;174.77679491043088" />

<input type="hidden" id="VEpin_msftve_1000_200002" value="This is pin 2;-41.28519169519274;174.77449893951424" />

<input type="hidden" id="VEpin_msftve_1000_200003" value="this is pin 3;-41.28699756258909;174.77278232574466" />



This hidden input contains some crucial information. The pin description (this will appear in the info box and also the Longitude and Latitude.) Since there is no right click in web we need to add some radio buttons. This will help determine what action the user wants to perform. So we add a radio group.

<input id="addPin" name="pinOptions" type="radio" value ="AddPin">Add Pin</input> <input id="removePin" name="pinOptions" type="radio" value ="RemovePin">Remove Pin</input> <input id="navigate" name="pinOptions" type="radio" value ="navigate" checked ="checked" >Navigate</input> Navigate</input>

Add Pin
Remove Pin
Navigate

It is pretty self explanatory.

3. Let's add first function GetMap();

function GetMap()
{
map = new VEMap('myMap');
map.LoadMap();

var LL = new VELatLong();
LL.Longitude = '174.77620487244477';
LL.Latitude ='-41.28656222412803';

map.SetCenter(LL);
map.SetZoomLevel(16);
map.AttachEvent('onmousedown',MouseHandler);
map.AttachEvent('onmouseup',MouseHandler);
map.AttachEvent('onmousemove',MouseHandler);
map.AttachEvent('onclick', OnMapClick);


var shape = new VEShape(VEShapeType.Pushpin, map.GetCenter());
shape.SetDescription('Provoke Solutions');
shape.SetMoreInfoURL('http://www.provoke.co.nz/');
shape.SetCustomIcon('http://localhost:1221/Desktop/provoke.jpg');
shape.SetLineColor(new VEColor(0,150,100,1.0));
shape.SetFillColor(new VEColor(0,100,150,0.5));
shape.ShowIcon();
map.AddShape(shape);


}

4. Load Pins

We now need to load

function loadPins()
{
var hiddenPins = document.getElementsByTagName("input");

for( i = 0; i < hiddenPins.length; i ++)
{
if (hiddenPins[i].getAttribute('type') == 'hidden')
{
var inputID = hiddenPins[i].getAttribute('id').substr(0,5);

if (inputID == 'VEpin')
{
var oldPin = hiddenPins[i].getAttribute('id').replace('VEpin_','');
var pinDetails = hiddenPins[i].value;

var arrPinDetails = pinDetails.split(";");
var LL = new VELatLong();
LL.Longitude = arrPinDetails[2];
LL.Latitude = arrPinDetails[1];


var newPin = new VEShape(VEShapeType.Pushpin,new VELatLong(LL.Latitude, LL.Longitude));
map.AddShape(newPin);
pinId = newPin.GetID();

defaultDescription = arrPinDetails[0];
newPin.SetDescription("<div id = 'description"+pinId+"'style = 'display :block';>"+defaultDescription+"</div> <br/>"+
"<a href='#' id = 'edit"+pinId+"' onclick ='EditPinDetails(this.id)'style = 'display :block';>Edit</a>"+
"<div id = 'textChangeArea"+pinId+"' style ='display:none'> <input id='newDescription"+pinId+"' type='text' maxlength = '150' />"+
"</div><a href='#' id = 'save"+pinId+"' onclick ='SavePinDetails(this.id)'style = 'display :none';>Save</a>" );
}

}


}

}


In the next post I will take you through all the functions and what they do and how they work!!!