Monday, July 26, 2010

Team Foundation Server 2010 Links

The past couple of days I've been working with a customer on their TFS 2010 implementation. During this process I've ran across some pretty good information. Below is a list of links and a brief description.

Team Foundation Installation Guide for Visual Studio 2010
Great help document for TFS installation planning.
http://www.microsoft.com/downloads/details.aspx?FamilyID=2d531219-2c39-4c69-88ef-f5ae6ac18c9f&displaylang=en

Configuring SharePoint Server 2010 for Dashboard Compatibility with TFS 2010
TFS ships with Windows SharePoint Service v3.0. This blog topic discusses how to configure TFS 2010 and SharePoint 2010 to work with each other.
http://blogs.msdn.com/b/team_foundation/archive/2010/03/06/configuring-sharepoint-server-2010-beta-for-dashboard-compatibility-with-tfs-2010-beta2-rc.aspx

Integrate SharePoint 2010 with TFS 2010
http://blog.hinshelwood.com/archive/2010/05/03/integrate-sharepoint-2010-with-team-foundation-server-2010.aspx

Microsoft Visual Studio Scrum 1.0
Microsoft’s new Scrum Process Template for TFS.
http://visualstudiogallery.msdn.microsoft.com/en-us/59ac03e3-df99-4776-be39-1917cbfc5d8e

Scrum for Team System Process Template v3.0
Pretty useful Scrum Process Template for TFS by EMC Consulting. Much more detailed than the Microsoft Visual Studio Scrum 1.0 process template.
http://www.scrumforteamsystem.com/version-3/process-template-x64

Team Foundation Server Power Tools
This is a very useful set of tools for modifying your TFS environment.
http://visualstudiogallery.msdn.microsoft.com/en-us/3e8c9b68-6e39-4577-b9b7-78489b5cb1da

TFS Integration Platform
This is a platform that allows for the integration of external systems with TFS.
http://tfsintegration.codeplex.com/

Urban Turtle
This is a very cool tool for TFS that makes managing your Scrum process simple.
http://urbanturtle.com/?item=home

Wednesday, April 7, 2010

Microsoft Ajax Minifier

I ran into this tool today. Been serveral times in the past where javascript minification has been asked. I've used a couple of other commonly used tools, however, this one seems promising. will look at using it in the future.

http://www.asp.net/ajaxLibrary/AjaxMinDocumentation.ashx

Thursday, April 9, 2009

Application Architecture Guide 2.0

Very interesting read.  Discusses everything from development technologies to platforms to design patterns.  Must read for someone new to the Microsoft stack.  Contributions from highly respected Microsoft MVPs.

http://apparchguide.codeplex.com/

Wednesday, April 1, 2009

Free eBook: ASP.NET MVC 1.0

Not necessarily an entire book but the entire first chapter.  Scott Guthrie and friends have published the first chapter of their new book “ASP.NET MVC 1.0” free for download.

http://weblogs.asp.net/scottgu/archive/2009/03/10/free-asp-net-mvc-ebook-tutorial.aspx

Sunday, March 22, 2009

jQuery: Leveraging Element Data

A common task when dealing with UI is displaying data.  When it comes to HTML and persisting data, things can get pretty interesting and ugly.  jQuery makes attaching data to HTML elements very simple.  Using the data method, you are able associate data with an element, given a key (this allows for multiple pieces of data to be associated to a single element).  Mix this with jQuery’s powerful selectors, we are able to create some interesting user experiences.  I’ve put together a sample in which we retrieve a series of Users and available Security Roles, from a .NET Web Service.  The UI allows a user to drag various users into their appropriate groups.

$(msg.d).each(function() {
$("<div></div>").addClass("item").text(this.Username).appendTo("#userList").data("__jsonData", this);
});
$(".user .item").draggable({ revert: true });

Once we get our response back from the GetUsers call, we iterate through each of the items in the response and create the HTML elements.  In doing so we additionally associate the JSON object with the new html element, using the key of “__jsonData”.  Finally, we make all the newly created elements draggable.


$(msg.d).each(function() {
var newContainer = $("<div></div>").addClass("container role").appendTo("body").data("__jsonData", this);
$("<div></div>").addClass("role-title").text(this.Name).appendTo(newContainer);
});
$(".role").droppable({
drop: function(event, ui) {
if (ui.draggable.hasClass("item")) {
var dropData = ui.draggable.data("__jsonData");
$("<div></div>").addClass("item").appendTo($(this).removeClass("over")).text(dropData.Username).data("__jsonData", dropData);
}
},
over: function(event, ui) { if (ui.draggable.hasClass("item")) $(this).addClass("over"); },
out: function(event, ui) { if (ui.draggable.hasClass("item")) $(this).removeClass("over"); }
});
$(".role").draggable({ handle: ".role-title" });
$(".user").draggable({ handle: ".title" });

Next, we make our call to the GetRoles web service.  Once, the call returns we again create the new HTML elements.  Each container will invoked the droppable.  We will feed it several parameters, mainly to signify if the draggable element is of the “item” type.  Since we’ve made the containers draggable, the drop target needs to know whether or not is a container or an item.



$("#report").click(function() {
var reportString = "";

$(".role").each(function() {
reportString += $(this).data("__jsonData").Name + "\r\n-------------\r\n";
$(this).children(".item").each(function() {
var itemData = $(this).data("__jsonData");
reportString += itemData.FirstName + " " + itemData.LastName + " (" + itemData.Username + ")\r\n";
});
reportString += "\r\n";
});

alert(reportString);
});

Finally, we want to summarize the data, once the user is done putting their users into the appropriate groups.  I’ve simply added a click handler to the “report” button.  This simple compiles a string of all roles and the users that were defined for the role.  Here we can see that we are putting the summary together based on attributes that are not displayed in the UI anywhere.  We are yanking this information out of the JSON object, that we stored in the jQuery data for the given elements.  We could easily add the User data to the Role.Users array and ship them off to an update web service.


So, as you can see, the jQuery element data allows you to create a pretty flexible UI without having to do anything like create hidden fields and/or complicate your HTML, simply to support tracking UI and data as one unit.


Download Source

Thursday, March 19, 2009

Elevated Permissions with SPContext

Old post I moved over.


I have created a provisioning wizard to control where and how sites are created. I do this through a web part that is added to the STS#1 definition. To prevent users from accessing the site settings menu everyone is setup at the top level as a "Reader". So obviously if i want to create a site, within the users context, i need to elevate their permission. There is plenty of code out there that demostrates the SPSecurity.RunWithElevatedPrivileges, however, if you are to use the SPContext while inside a call to RunWithElevatedPrivileges it does not elevate the current context permission. You will have to open a new site. Examples below:


// Doesn't Work
SPSecurity.RunWithElevatedPrivileges(delegate {
SPWeb web = SPContext.Current.Web {

// provision site & do other jazz
web.Webs.Add(...);
});

// Better
SPSecurity.RunWithElevatedPrivileges(delegate {
using (SPSite site = new SPSite(SPContext.Current.Web.Url)) {
using (SPWeb web = site.OpenWeb()) {
// provision site & do other jazz
web.Webs.Add(...);
}
}
});

Odd but works for me.

Tuesday, March 17, 2009

ASP.NET Web Services, JSON, and jQuery

I've recent found jQuery as a very powerful tool. It simplifies a lot of how the DOM is traversed. Additionally, it makes writing JavaScript more consistent and bringing a lot of what newer languages contain right from the get go. With jQuery you can really build powerful web applications without having to spend hours writing JavaScript to do some very trivial operations.

One of many things that jQuery simplifies is making AJAX calls. Invoke call to the “ajax” method, wire up a delegate to handle various response types and presto--instant Ajax. These calls are especially easy when arguments and return values are of basic data types (string, int, float, etc). Passing in the data attribute a JSON representation of the parameters on the web service (e.g. { parameterName: parameterValue} ) . Though, sometimes it is necessary to pass complex data types to a web service. Here I’ll illustrate how to do this.

Below I've create some very simple page level web services. Services defined within a pages scope are automatically ScriptServices and do not require the denotation. I'll explain more on ScriptServices later.

[WebMethod()]
public static List<Post> GetPosts()
{
List<Post> posts = new List<Post>();
posts.Add(new Post("JSON Rules!", "Some body text", "Johnnie Beam"));
posts.Add(new Post(".NET Rocks!", "More body text", "Jim Daniels"));
posts.Add(new Post("jQuery Pwns!", "Some more body text", "Jack Walker"));

return posts;
}

[WebMethod()]
public static string CreatePost(Post post)
{
return "server received: " + post.Title;
}

The GetPosts method returns a list of Post objects. While CreatePost takes a Post object as an argument, simply returning a string. The Post class for these objects is identified below.


public class Post
{
public string Title { get; set; }
public string Body { get; set; }
public string Author { get; set; }

public Post(string title, string body, string author)
{
this.Title = title;
this.Body = body;
this.Author = author;
}

public Post() { }
}

One thing to note is, I've explicitly identified an empty, zero argument constructor. Reason that this is necessary is due to the way .NET handles the service request. It takes the data and creates a new instances of all arguments and assigns values appropriately (this process is known as Deserialization).

Now that we have our sample services, it's time that we invoke them. Below I've created a sample that will do just that.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>WebService Sample</title>
<script type="text/javascript" language="javascript" src="scripts/jquery-1.3.2.js"></script>
<script type="text/javascript" language="javascript" src="scripts/json2.js"></script>
<script type="text/javascript" language="javascript">
$("document").ready(function() {
// wire up save click
$("#save").click(function() {
Save($("#title").val(), $("#body").val(), $("#author").val());
});

// load listings from server
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "webservice.aspx/GetPosts",
data: "{ }",
dataType: "json",
success: function(msg) {
$(msg.d).each(function() {
var newElement = $("<div></div>");
newElement.append("<h3>" + this.Title + "</h3>");
newElement.append("<p>" + this.Body + "</p>");

$("#postListing").append(newElement);
});
}
});
});

function Save(title, body, author) {
var parameters = { post: { Title: title, Body: body, Author: author} };

$.ajax({
type: "POST",
url: "webservice.aspx/CreatePost",
data: JSON.stringify(parameters),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#result").text(msg.d);
}
});
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<span id="result"></span>

<div>
<h2>Create Post</h2>
<span>Title: </span><input type="text" id="title" /><br />
<span>Body: </span><textarea id="body" rows="3" cols="30" ></textarea><br />
<span>Author: </span><input type="text" id="author" /><br />
<button id="save">Save</button>
</div>

<div id="postListing">
<h2>Post Listing</h2>
</div>
</div>
</form>
</body>
</html>

Before I explain what is going on here, let’s take a little bit of a dive into ScriptServices. ASP.NET AJAX introduces the concept of ScriptServices. ScriptServices can be called in a much more simplistic manner, as compared to SOAP services. SOAP Services contain a large amount of data that is expressed in XML. Making SOAP very verbose and impacting overall performance. ScriptServices are an attempt at making web service more RESTful. REST services streamline the process by using the existing HTTP infrastructure, rather than complicated SOAP messages; typically using JSON as data format. There is a lot that can be said on this topic--I won't go into that discussion here.

Back to the sample--Once the DOM is ready we setup the "Save" click handler and then make a call to the GetPosts method. Here we signify that the resulting data type will be a JSON object. This is possible because we've identified the content type of the request to be "application/json; charset=utf-8". This tells ASP.NET, this message needs to be handled as a ScriptService.

When the call successfully completes, the JSON object from the web service is passed to the Success handler (as a note the JSON object is actually wrapped in a "d" object. My assumption here is that this is done for future compatibility. Potentially the ScriptService, in the future, may pass along various information from the server.) Here we simply create a new DIV elements for all items returned, displaying the title and body.

When the user clicks on the Save button, the values of the various input fields are passed into the Save function. The save function first creates a JSON object that identifies the parameters to be sent back to the ScriptService. Then an ajax call is made. This call looks very similar to the GetPosts call, however, the data property is very much different. Here we perform a stringify on the parameters object. The stringify call takes a JSON object and turns into its string representation.

NOTE: stringify method comes from the json2.js file. More information on this can be found here.

TIP: A technique that I use when I'm not sure of the data being passed to the success event, I will stringify the msg.d object and pass that into an alert. This provides a good way of visualizing what the object looks like.

alert(JSON.stringify(msg.d));

Here we've demonstrated that you can take a complex data type and bring it down from a service, additionally, you can build a JSON object from JavaScript and send it into a .NET ScriptService. This paradigm makes web 2.0 style development effortless.