Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Thursday, April 10, 2014

How to Install SharePoint 2013 Project Templates on Visual Studio 2012


  1. Download and install Web Platform Installer: http://www.microsoft.com/web/downloads/platform.aspx.
  2. Close all VS instances or the setup will fail.
  3. On the Web PI select "Microsoft Office Developer Tools for Visual Studio 2012".
After that open VS and the SharePoint 2013 templates should be on the New Project dialog, under Installed | Templates | <language> | Office/SharePoint | SharePoint Solutions.

Tuesday, February 2, 2010

Using Microsoft.SharePoint.dll to find out the ID of a list

When moving a site between web applications using SharePoint Designer backup (Site > Administration > Backup Web Site menu), several web parts wich had been converted to XSLT were displaying a "strange" message:

The server returned a non-specific error when trying to get data from the data source. Check the format and content of your query and try again. If the problem persists, contact the server administrator.

When an web part is converted to XSLT, SharePoint Designer places on the page a control of type WebPartPages:DataFormWebPart to display the data. This control uses the list ID to specify wich list is the data source (each list in a SharePoint site is given a GUID as its identifier, wich is stored in the list's ID property). Well, when the site was recreated at the destination, so were its lists, and that generated new ID's to them. And the web parts could not find their lists anymore, so they stopped working.

Being a restless geek, I decided to test the classes on Microsoft.SharePoint.dll by coding a little console app that listed the ID's from a SharePoint site lists. The code is bellow, and can be used as an intro to classes in namespace Microsoft.SharePoint. If you want just the app, just download the following file and run it from a command prompt on your SharePoint machine: SPListId.zip.

Imports Microsoft.SharePoint

Module Module1

Sub Main()
Try
Console.WriteLine()
If My.Application.CommandLineArgs.Count = 0 Then
Console.WriteLine("SPListId - Lists IDs from lists in a SharePoint site")
Console.WriteLine("Copyright (c) 2010 SrNimbus. No rights reserved ;)")
Console.WriteLine("Usage: SPListId site_url")
Return
End If
' The System.Uri class helps manipulating network addresses
Dim urlSite As Uri = New Uri(My.Application.CommandLineArgs(0))
' The Microsoft.SharePoint.SPSite class represents a site collection on SharePoint
Dim siteCollection As New SPSite(urlSite.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped))
' The Microsoft.SharePoint.SPWeb class represents a site on a site collection
Dim site As SPWeb = siteCollection.OpenWeb(urlSite.AbsolutePath)
Console.WriteLine("Lists on {0}:", urlSite.OriginalString)
Console.WriteLine("------------------------------------")
' The SPList class represents a SharePoint list
For Each lista As SPList In site.Lists
Console.WriteLine("{0}: {{{1}}}", lista.Title, lista.ID.ToString().ToUpper())
Next
Console.WriteLine("------------------------------------")
Catch erro As Exception
Console.WriteLine("Ooops:")
Console.WriteLine("{0} - {1}", erro.Source, erro.Message)
Finally
Console.WriteLine()
End Try
End Sub

End Module

Remember to add a reference to Microsoft.SharePoint.dll in order to compile the project. It is located on the SharePoint server, at %ProgramFiles%\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI.

Friday, December 18, 2009

SELECT * FROM Table JOIN... ListBox???

A Linq way to retrive rows from one table based on rows from a related table whose lines are loaded into a listbox.

The ASP.NET test WebForm:



I want all products related to the selected categories (ListBox.SelectionMode = Multiple). The project is an ASP.NET Web App on VS 2010 Beta 2, and it contains an Entity Data Model on the Northwind sample database.

The LinkButton code:

    Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.Click
Dim data As New NorthwindEntities
Dim selectedCategoriesProducts As New List(Of Products)
selectedCategoriesProducts = _
(From line As Products In data.Products
Join item As Integer In (From x In ListBox1.Items Where x.Selected = True Select x.value)
On line.CategoryID Equals item
Select line).ToList()
GridView1.DataSource = selectedCategoriesProducts
GridView1.DataBind()
End Sub
The Linq (to Entity) query joins the Products table (data.Products) to a integer list (Join item As Integer). The integer list is generated by a Linq (to Objects) query that selects the values (Select x.value) from the listbox options (ListBox1.Items) that are checked (Where x.Selected = True). The returned Products object list is then shown on the GridView.

In other words, we joined the Products table on Nortwind database with the ListBox selected items from an webform. Well, talk about data source abstraction... :-)

"Linq Is Fun!!!"
Buda On Using Linq To Query Data

Monday, November 9, 2009

Visual Studio: how to target different .NET Framework versions

We are creating a WPF application on Visual Studio 2010 (beta 1), but Blend 3 doesn’t load .NET Framework 4.0 assemblies. So on the designer’s machine we had to compile the solution targeting .NET Framework version 3.5.

(quick thought: our development team is made up of one designer, one product manager, and one project manager. So, WHO IS CODING???)

We found an article on MSBuild – Microsoft’s build engine – about the /toolsversion option, that targets specific .NET Framework versions. We built a .bat file that recompiles all projects in the solution. Following is some of it:

msbuild StorageClient\StorageClient.csproj /toolsversion:3.5 /verbosity:quiet
if ERRORLEVEL 1 goto erro

MSBuild recognizes Visual Studio project files, and activates the corresponding compiler. The /toolsversion option selects the target .NET Framework version (allowed values are 2.0, 3.0, 3.5 and 4.0), and overrides the selected version on the project file. The following “if” checks if MSBuild returned 1, which signals an error, so you can stop the build job (using good(?) old goto).

A lot less painful than I thought. The same batch will be used to generate a 3.5 version of the solution when building the tables on Azure Development Storage, because DevTableGen – the utility that builds the tables – also does not support 4.0 .NET Framework assemblies.

MSBuild location is not included on the standard command prompt path, so use Visual Studio 2010 command prompt (VS 2010 program group > Visual Studio 2010 Tools).

Sunday, October 11, 2009

Global error handling in ASP.NET and Windows Forms

You should not let exceptions unhandled in *any* part of your application. But that doesn't mean you have to spray your entire code with a swarm of try/catch blocks. Both Windows Forms and ASP.NET applications offer the possibility to create a global error handler, that will be activated whenever an unhandled exception (i.e., an exception that has not happened inside a try/catch block) occurs.

Windows Forms Global Exception Handler

As always, things are easier in Windows Forms than in ASP.NET. Windows Forms provides the developer with the Application object, that among other things has the ThreadException event. Basically, all you have to do is to add an even handler to the ThreadException event, and your global event handler is set.

Create a new VB.NET Windows Forms project, add a button to the Form1 form, and replace its code with the following:


Imports System.Diagnostics

Public Class Form1

Const MYAPP_SOURCE_NAME As String = "My Application"

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Creates the event source on Windows Application Log
' This has to be done only once, usually during app setup
If Not EventLog.SourceExists(MYAPP_SOURCE_NAME) Then
EventLog.CreateEventSource(MYAPP_SOURCE_NAME, "Application")
End If
' Designates the global error handler
AddHandler Application.ThreadException, AddressOf Me.TheGlobalErrorHandler
End Sub

Sub TheGlobalErrorHandler(ByVal sender As Object, ByVal e As Threading.ThreadExceptionEventArgs)
' This is how we get the exception data
Dim unhandledException As Exception = e.Exception
' Writes technical error information to the Application Log
EventLog.WriteEntry(MYAPP_SOURCE_NAME, _
"Unhandled error: " + vbNewLine + unhandledException.ToString(), _
EventLogEntryType.Error)
' Some nice message to the user
MsgBox("An unexpected error has occured. Technical error information " & _
"has been writen to the Windows Application Log.", _
MsgBoxStyle.Critical)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' Simulates an unhandled exception
Throw New Exception("Oh oh error accessing the database")
End Sub
End Class



Click on the button to simulate an unhadled exception. A message is displayed and if you look at the Windows Application Log on EventViewer (Start > Run > eventvwr.msc), there it is the exception.

ASP.NET Global Exception Handler

ASP.NET provides you with the Application_Error global application event, that is fired whenever an unhandled exception occurs. This event handler belongs to the global application class, as Visual Studio calls it. The global application class code is located on the Global.asax file. ASP.NET applications, by default, don't have a Global.asax file. You can add one by going to the Project menu and selecting Add New Item > Global Application Class.

On the Application_Error event handler code, you have to use two special methods:
  • Server.GetLastError() gives access to the unhandled exception.
  • Server.ClearError() prevents ASP.NET from showing the default error page.
Create a new ASP.NET Web Application, add a Global.asax file to it, and replace the code in Global.asax.vb with the following:

Imports System.Web.SessionState
Imports System.Diagnostics

Public Class Global_asax
Inherits System.Web.HttpApplication

Const MYAPP_SOURCE_NAME As String = "My Application"

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
' Creates the event source on Windows Application Log
' This has to be done only once, usually during app setup
If Not EventLog.SourceExists(MYAPP_SOURCE_NAME) Then
EventLog.CreateEventSource(MYAPP_SOURCE_NAME, "Application")
End If
End Sub

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Stores the unhandled exception
Dim unhandledException As Exception = Server.GetLastError()
' Says to the Framework "Don't show default error page - we will handle it"
Server.ClearError()
' Writes techinical error information to the Application Log
EventLog.WriteEntry(MYAPP_SOURCE_NAME, _
"Unhandled error: " + vbNewLine + unhandledException.ToString(), _
EventLogEntryType.Error)
' Redirects user to some page with nice error message
Response.Redirect("/error.aspx")
End Sub

End Class


Create a page named "error.aspx"; that's the page users will be redirected to after an unhandled exception.

Finnaly, add a Button to Default.aspx, and replace its code with the following:

Partial Public Class _Default
Inherits System.Web.UI.Page

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
' Simulates an unhandled exception
Throw New Exception("Oh oh that database access error again")
End Sub
End Class


Click on the button and you will be redirected to error.aspx, and an event will be logged on the Application Log with the exception data.



UPDATE: the Application_Start code will fail on Windows Vista & Windows 7, because of tightened security. The code tries to create an event source in order to log events to it. The methods EventLog.SourceExists() and EventLog.Create() both try to scan the Windows Logs to check if the specified source exists, but access to the Security Log by ASP.NET apps is not allowed by default. There are several ways to "do it right", but a quick and dirty solution is to create the following registry key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\eventlog\Application\YOUR_APP_NAME, changing YOUR_APP_NAME to the event log source you want to create. A possible way to "do it right" is to create a command line app containing the Application_Start code, and set it to run from your site's setup package.

Monday, September 28, 2009

Multiple Check-outs on TFS

Team Foundation Server Source Code Control comes with default options that can cause some problems to developers coming from Visual SourceSafe.
  1. Multiple check-outs of the same file are allowed by default. When you try to check in code that has been modified by another developer, a merge conflicts screen appears for you to select what you want to keep and what you want to discard, from yours modifications and from other's too. That can be quite a pain if the file has been through many modifications.

  2. Receiving the latest version of a file on check-out is *not* a default setting. So, even if you disable multiple check-outs, you may still find yourself at the merge conflicts screen, because you worked on code that doesn't have the most recent modifications made to it.
If you like single check-out and think modifications merging is a bad ideia, you have to change the default TFS SCC options. Open the project on Team Explorer, double click Source Code and, on the Team menu, select Team Project Settings > Source Control. Then, reverse selections:



That way there will be no two developers working on the same code at the same time, and you will always be editing the latest version of any code you check out.

Thursday, September 10, 2009

Could not load file or assembly CrystalDecisions.CrystalReports.Engine

If your ASP.NET application does reporting with the Crystal Reports version that comes with Visual Studio 2008 - Crystal Reports 2008 Basic - when you deploy that application to a fresh IIS installation, you will get the message "Could not load file or assembly 'CrystalDecisions.CrystalReports.Engine, Version=10.5.3700.0" etc etc etc. That's because the site needs the Crystal Reports runtime. There's a MSI installation package on machines with VS2008 installed, at C:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\CrystalReports10_5. Install the correct MSI (there's one for 32- and another for 64-bit machines), and the application should run ok.