Thursday 4 July 2013

C# - How to Fetch a Report from SQL Server Reporting Services (SSRS)

Tested with SSRS 2008, may well work with 2005 too. You'll need to add a Service Reference in your project to the SSRS API, which will generate the ReportExecutionServiceSoapClient proxy seen here. You can request the report in various formats: "PDF", "WORD", or "EXCEL".
 class ReportFetcher  
   {  
     public enum ReportFileFormat  
     { PDF }  
     /// <summary>  
     /// Makes a call to a a SSRS server to load and render a report in a certain file format  
     /// </summary>  
     /// <param name="pathToReport">Path to the report on the server (including name)</param>  
     /// <param name="execParams">Execution parameters</param>  
     /// <param name="fileFormat">Rendering file format</param>  
     /// <returns></returns>  
     public byte[] ToFile(string pathToReport, List<ParameterValue> execParams, string format = "PDF")  
     {  
       ExecutionInfo execInfo;  
       var trusteduserHeader = new TrustedUserHeader();  
       var execHeader = new ExecutionHeader();  
       ServerInfoHeader serviceInfo;  
      
       var client = new ReportExecutionServiceSoapClient();  
       if (client.ClientCredentials == null)  
       {  
         throw new NullReferenceException("Client Credentials are null");  
       }  
       client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;  
       client.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;  
       // Load the report  
       client.LoadReport(trusteduserHeader, pathToReport, null, out serviceInfo, out execInfo);  
       execHeader.ExecutionID = execInfo.ExecutionID;  
       client.SetExecutionParameters(execHeader, trusteduserHeader, execParams.ToArray(), "en-us", out execInfo);  
       // Render the report  
       string extension;  
       string encoding;  
       string mimeType;  
       string[] streamIds;  
       var warnings = new Warning[1];  
       warnings[0] = new Warning();  
       Byte[] result;  
       client.Render(execHeader, trusteduserHeader, format, null, out result, out extension, out mimeType, out encoding, out warnings, out streamIds);  
       ConnectionHelper.SafelyCloseConnection(client);  
       return result;  
     }  
   }  

If you want to save the returned byte array to a file, it's easily done like this:
using (var stream = File.OpenWrite("myReport.pdf"))
{ stream.Write(result, 0, result.Length);
}

Tuesday 2 July 2013

C# ASP.NET MVC4 - How to Generate an Atom or RSS Feed

.NET's syndication classes make creating RSS/Atom feeds easy. Here's how to do it in ASP.NET MVC. We're using Atom below, but switching to RSS is simply a matter of changing the Atom10FeedFormatter to Rss20FeedFormatter.

The feed url in this example would be http://myserver/myappname/feed

 public class FeedResult : ActionResult  
   {  
     public Encoding ContentEncoding { get; set; }  
     public string ContentType { get; set; }  
     private readonly SyndicationFeedFormatter _feed;  
     public SyndicationFeedFormatter Feed  
     {  
       get { return _feed; }  
     }  
     public FeedResult(SyndicationFeedFormatter feed)  
     {  
       _feed = feed;  
     }  
     public override void ExecuteResult(ControllerContext context)  
     {  
       if (context == null)  
         throw new ArgumentNullException("context");  
       HttpResponseBase response = context.HttpContext.Response;  
       response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/rss+xml";  
       if (ContentEncoding != null)  
         response.ContentEncoding = ContentEncoding;  
       if (_feed != null)  
       {  
         using (var xmlWriter = new XmlTextWriter(response.Output))  
         {  
           xmlWriter.Formatting = Formatting.Indented;  
           _feed.WriteTo(xmlWriter);  
         }  
       }  
     }  
   }   
 

 
   public class FeedController : Controller  
   {  
     private readonly IPostingDataSource _db;  
     private static readonly Settings Settings = new Settings();  
     private const int ItemContentLength = 500; 
 
     public FeedController()  
     {  
       _db = new PostingDbContext();  
     }  
     public ActionResult Index()  
     {  
       string appUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Request.ApplicationPath;  
       string detailsUrl = appUrl + "/Home/Details/";  
       var postItems = _db.Postings  
           .OrderByDescending(x => x.AddedDate)  
           .Take(20)  
           .AsEnumerable()  
           .Select(p => new SyndicationItem(p.Title, TruncateLongString(p.Body, ItemContentLength, true), new Uri(detailsUrl + p.Id), p.Id.ToString(), new DateTimeOffset(p.AddedDate)));  
       var feed = new SyndicationFeed("bCay Auctions", "Buy! Sell!", new Uri(appUrl), postItems)  
       {  
         Copyright = new TextSyndicationContent("Codestruck Productions"),  
         Language = "en-US"  
       };  
       feed.Authors.Add(new SyndicationPerson(Settings.Email, "Codestruck", appUrl));  
       // Can change from Atom to RSS here  
       return new FeedResult(new Atom10FeedFormatter(feed));  
     }  
     private static string TruncateLongString(string str, int maxLength, bool addEllipsis)  
     {  
       if (str.Length <= maxLength)  
         return str;  
       string result = str.Substring(0, Math.Min(str.Length, maxLength));  
       if (addEllipsis)  
         result += "...";  
       return result;  
     }  
   }  

Monday 1 July 2013

Welcome to Codestruck

I've started this blog as a place to keep useful code snippets, whether I come across them on-line or code I've written myself. Keeping stuff here in on place will certainly be useful to me, and I hope others will find it useful too.

Codestruck. Like star-struck, but less celebrity-spotting and more bug-spotting.