Ilya Verbitskiy

Thoughts and links about computer programming
posts - 15 , comments - 230 , trackbacks - 0

Sunday, February 23, 2014

Support old browsers in MvcReportViewer

Last time I released a feature which allow users to send data to Report Viewer’s IFRAME using HTTP POST request. The overall feedback I heard from the users was pretty good. And then the problem came…

I did not want to support legacy browsers like IE 6, 7 and 8, because it would force me to write a lot of additional JavaScript code to deal with DOM in the right way. And I am still hoping that IE < 10 will die soon. Unfortunately it had not been the right decision.

Please tell me who are the biggest SSRS users… Enterprises. It is easy to guess, isn’t it? The problem with enterprises is they are slow in technology adaptation. And Internet Explorer 8 is one of the most used browsers there. To make long story short, there are developers who must support IE 8 in their applications, but they use MvcReportViewer to simplify their job (I hope :-) ).

Today I release MvcReportViewer 0.3.1 with old browsers support. But there is a disadvantage. I used jQuery 1.11.0 for DOM manipulations. Make sure you add jQuery to your web-page.

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>

Posted On Sunday, February 23, 2014 3:02 PM | Comments (3) | Filed Under [ SQL Server Projects ]

Monday, January 20, 2014

MvcReportViewer v.0.3.0 is available!

 

Thank you everybody for useful feedback, suggestions, bug ad bug fixes. Today I have published the latest changes on NuGet.

  • Added Method(FormMethod) method to Fluent interface to specify the way to send parameters to the iframe. FormMethod.Get is default. All parameters sent in URL. FormMethod.Post created a hidden form on the page and submits it to the iframe. This method allows sending long parameters to the report. FormMethod.Post works in IE 9.0, Chrome 0.2, Firefox 1.0, Opera 9.0 and Safari 3.1 or newer versions.
  • Added support for report parameter’s multiple values to report viewer extensions:
    • Fluent interface: MultipleReportParameters (IEnumerable<KeyValuePair<string, object>> reportParameters)
    • @Html.MvcReportViewer(string reportPath, IEnumerable<KeyValuePair<string, object>> reportParameters, object htmlAttributes)
  • Added support for report parameter’s multiple values to report runner:
    • FileStreamResult Report(this Controller controller, ReportFormat reportFormat, string reportPath, IEnumerable<KeyValuePair<string, object>> reportParameters)
    • FileStreamResult Report(this Controller controller, ReportFormat reportFormat, string reportPath, string reportServerUrl, IEnumerable<KeyValuePair<string, object>> reportParameters, string username = null, string password = null)
  • Removed ShowParameterPrompts setting. You can set all Report Viewer control’s UI settigns using ControlSettings(ControlSettings settings) method from fluent interface.
  • Fixed bug in Chrome browser.

There are still a lot of things to do. First of all I would like to implement Local Mode support. There were several people asking about this functionality. Unfortunately I still do not have clear idea how to do it nicely. Then I would like to migrate the project to ASP.NET MVC 5 and create special versions for ASP.NET MVC 3 and 4.

Posted On Monday, January 20, 2014 12:45 AM | Comments (5) |

Monday, November 25, 2013

MvcReportViewer v.0.2.0 is available!

I am glad to see that people started to use my small library. I released new version few days ago.

I added a possibility to download SSRS reports in MS Word, MS Excel, PDF or Image format directly from your controller. You can do that using Report extension method Controller class. The method always returns an instance of FileStreamResult class:

  1. FileStreamResult Report(ReportFormat reportFormat, string reportPath)
  2. FileStreamResult Report(ReportFormat reportFormat, string reportPath, object reportParameters)
  3. FileStreamResult Report(ReportFormat reportFormat, string reportPath, string reportServerUrl, string username = null, string password = null, object reportParameters = null)

Where reportFormat might be ReportFormat.Excel, ReportFormat.Word, ReportFormat.PDF or ReportFormat.Image.

The following code allows user to download the report in MS Excel format.

public ActionResult DownloadExcel()
{
    return this.Report(
        ReportFormat.Excel,
        "/Reports/TestReport",
        new { Parameter1 = "Hello World!", Parameter2 = DateTime.Now, Parameter3 = 12345 });
}

 

UPDATE: I released version 0.2.1 few minutes ago. The latest version has the bug-fix for the issue when it was not possible to use the helper in cluster environment when StateServer or SQLServer session state containers had been used. Bug Report.

Posted On Monday, November 25, 2013 6:35 PM | Comments (9) |

Monday, November 4, 2013

SQL Server Reporting Services Report Viewer wrapper for ASP.NET MVC has been released!

SQL Server Reporting Services is rich and popular reporting solution that you have free with SQL Server. It is widely used in the industry: from small family businesses running on SQL Server 2008/2012 express to huge corporations with SQL Server clusters.

There is one issue with the solution. Microsoft has not release SSRS viewer for ASP.NET MVC yet. That is why people usually mixing modern ASP.NET MVC enterprise applications with ASP.NET Web Forms pages to view report.

Today I released ASP.NET MVC HTML helper which renders a basic ASP.NET Web Forms ReportViewer control inside an iframe.

You can get it from NuGet. The package name is MvcReportViewer.

The documentation and source code are available on GitHub under MIT license: https://github.com/ilich/MvcReportViewer.

Bug reports, patches and other contributions are welcome!

Posted On Monday, November 4, 2013 7:01 PM | Comments (20) |

Wednesday, October 16, 2013

Microsoft ReportViewer SetParameters continuous refresh issue

I am a big fun of using ASP.NET MVC for building web-applications. It allows us to create simple, robust and testable solutions. However, .NET world is not perfect. There is tons of code written in ASP.NET web-forms. You cannot simply ignore it, even if you want to.

Sometimes ASP.NET web-forms controls bring us non-obvious issues. The good example is Microsoft ReportViewer control. I have an example for you.

   1:  <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
   2:  <%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
   3:   
   4:  <!DOCTYPE html>
   5:   
   6:  <html xmlns="http://www.w3.org/1999/xhtml">
   7:  <head runat="server">
   8:      <title>Report Viewer Continiuse Resfresh Issue Example</title>
   9:  </head>
  10:  <body>
  11:      <form id="form1" runat="server">
  12:      <div>
  13:          <asp:ScriptManager runat="server"></asp:ScriptManager>
  14:          <rsweb:ReportViewer ID="_reportViewer" runat="server" Width="100%" Height="100%"></rsweb:ReportViewer>
  15:      </div>
  16:      </form>
  17:  </body>
  18:  </html>

 

The back-end code is simple as well. I want to show a report with some parameters to a user.

   1:  protected void Page_Load(object sender, EventArgs e)
   2:  {
   3:      _reportViewer.ProcessingMode = ProcessingMode.Remote;
   4:      _reportViewer.ShowParameterPrompts = false;
   5:   
   6:      var serverReport = _reportViewer.ServerReport;
   7:      serverReport.ReportServerUrl = new Uri("http://localhost/ReportServer_SQLEXPRESS");
   8:      serverReport.ReportPath = "/Reports/TestReport";
   9:   
  10:      var reportParameter1 = new ReportParameter("Parameter1");
  11:      reportParameter1.Values.Add("Hello World!");
  12:   
  13:      var reportParameter2 = new ReportParameter("Parameter2");
  14:      reportParameter2.Values.Add("10/16/2013");
  15:   
  16:      var reportParameter3 = new ReportParameter("Parameter3");
  17:      reportParameter3.Values.Add("10");
  18:   
  19:      serverReport.SetParameters(new[] { reportParameter1, reportParameter2, reportParameter3 });
  20:  }

 

I set ShowParametersPrompts to false because I do not want user to refine the search. It looks good until you run the report. The report will refresh itself all the time.

The problem caused by ServerReport.SetParameters method in Page_Load. The method cause ReportViewer control to execute the report on the NEXT post back. That is why the page has continuous post-backs.

The fix is very simple: do nothing if Page_Load method executed during post-back.

   1:  protected void Page_Load(object sender, EventArgs e)
   2:  {
   3:      if (IsPostBack)
   4:      {
   5:          return;
   6:      }
   7:   
   8:      _reportViewer.ProcessingMode = ProcessingMode.Remote;
   9:      _reportViewer.ShowParameterPrompts = false;
  10:   
  11:      var serverReport = _reportViewer.ServerReport;
  12:      serverReport.ReportServerUrl = new Uri("http://localhost/ReportServer_SQLEXPRESS");
  13:      serverReport.ReportPath = "/Reports/TestReport";
  14:   
  15:      var reportParameter1 = new ReportParameter("Parameter1");
  16:      reportParameter1.Values.Add("Hello World!");
  17:   
  18:      var reportParameter2 = new ReportParameter("Parameter2");
  19:      reportParameter2.Values.Add("10/16/2013");
  20:   
  21:      var reportParameter3 = new ReportParameter("Parameter3");
  22:      reportParameter3.Values.Add("10");
  23:   
  24:      serverReport.SetParameters(new[] { reportParameter1, reportParameter2, reportParameter3 });
  25:  }

You can download sample code from GitHub - https://github.com/ilich/Examples/tree/master/ReportViewerContinuousRefresh

Posted On Wednesday, October 16, 2013 11:34 PM | Comments (1) |

Thursday, October 10, 2013

How to change recovery mode for all databases

Changing recovery mode from FULL to SIMPLE for a SQL Server database is not a big deal. You can do it with one simple command.

   1:  USE master
   2:  ALTER DATABASE YourDatabase SET RECOVERY SIMPLE

 

But it might be tricky task to do for all databases on your server. Of course, you can to generate a script using using any programming language. I usually use F# for such “quick and dirty” solutions.  This time I solved the problem with T-SQL. I had to change recovery mode for more then 200 databases.

   1:  declare @name sysname,
   2:          @recovery_model_desc nvarchar(120),
   3:          @script nvarchar(500),
   4:          @full_backup_count int
   5:   
   6:  select @full_backup_count = count(*) from sys.databases where recovery_model_desc = 'FULL'
   7:  print 'There are ' + cast(@full_backup_count as varchar) + ' with FULL backup set'
   8:   
   9:  declare db cursor 
  10:      for select name, recovery_model_desc from sys.databases where recovery_model_desc = 'FULL'
  11:      for read only
  12:   
  13:  open db
  14:  fetch next from db into @name, @recovery_model_desc
  15:  while @@fetch_status = 0
  16:  begin
  17:      set @script = 'alter database [' + @name + '] set recovery simple'
  18:      exec sp_executesql @script
  19:      print 'Done with ' + @name
  20:      fetch next from db into @name, @recovery_model_desc
  21:  end
  22:   
  23:  close db
  24:  deallocate db
  25:   
  26:  select @full_backup_count = count(*) from sys.databases where recovery_model_desc = 'FULL'
  27:  print 'There are ' + cast(@full_backup_count as varchar) + ' with FULL backup set'

 

The script worked for me. Please make sure that you are using the script on your own risk, and I am not responsible for potential data damage.

You may find additional information about changing database recovery mode in View or Change the Recovery Model of a Database (SQL Server) article.

Posted On Thursday, October 10, 2013 6:30 AM | Comments (0) |

Tuesday, July 9, 2013

.NET Compilation - Part 1: Just-In-Time Compiler.

I spent last few weeks working on startup time improvements for a .NET Windows application. Over the next few weeks I’m going to share this experience and write a series of posts about JIT compilation and some interesting stuff you can do with it.

Let’s start. Today I am going to talk about JIT Compilation: what it is and how it works.

There are two types of compilers: compilers which do explicit compilation and compilers which do implicit one.

Explicit Compilation is a process when compiler converts source code directly to machine code which is understandable by CPU. C and C++ compilers are great examples of Explicit Compilation.

Implicit Compilation is a two-steps process, and it requires a Virtual Machine to be able to execute your code. The first step of the process is converting your program to a bytecode understandable by Virtual Machine. .NET bytecode is called Common Intermediate Language or CIL. It is also known as Microsoft Intermediate Language (MSIL) or just Intermediate Language (IL). I am going to use its official name Common Intermediate Language (CIL). The first step is done by a compiler (C#, VB.NET, etc.).

The second step is converting CIL code to a machine code running on metal. This is Virtual Machine’s task. Common Language Runtime (.NET Virtual Machine) converts only executed CIL fragments into CPU instructions at runtime.

NET_CLI

 

Just-In-Time Compilation

Just-In-Time compilation the process of converting CIL to machine code translation. In .NET world it is done by JIT Compiler (JIT or Jitter) which is a part of Common Language Runtime.

Let’s take a look how it works. You run a .NET application. First of all, CLR creates an internal data structure for all reference types and their methods. Each method references a procedure compiling CIL to machine instructions. Next your program calls a method. CLR sees that the methods points to the Jitter and starts it. Compiler reads CIL from metadata, verifies it, allocates memory and compiles the bytecode. Then  the reference to JIT compiler is replaced with a reference to the compiled block of code. The last step is to jump to the machine code and run it.

Next time, when program calls the same method, CLR executed compiled CPU instructions.

This process adds a little overhead for the first method call. Usually your application calls methods over and over again, and you will not see any performance problem at all.

JIT stored compiled code in dynamic memory. It means that you will compile your application twice if you run it two times simultaneously.

Jitter does not persist its work between runs of you application. The reason for that is it checks your current system state (CPU type, CPU count, etc.) and tries to generate optimized code for your current situation. When you will run you application next time, you may have different system state, and Jitter’s output will be different as well.

JIT Types

There are two types of JIT compilers available in the latest .NET Framework version.

  • Normal-JIT Compiler. This is the compiler I have described above. It compiles methods in runtime as needed.

  • Pre-JIT Compiler. It compiles the entire assembly before it has been used. Usually the compilation happens during application deployment. You can pre-compile an assembly using Ngen.exe tool (Native Image Generator).

.NET Framework 1.0 and 1.1 had the third JIT Compiler - Econo-JIT. It was a runtime compiler which hadn’t done any optimization and removed methods’ machine code when it is not required. It was done to improve compilation time. The compiler is obsolete since .NET 2.0 and you cannot enable it anymore.

JIT vs. Ngen

At the end I would like to compare Normal-JIT compiler and Pre-JIT compiler (Ngen).

Normal-JIT compiler is the best option for almost all cases because

  1. It may take advantage of your current hardware. For example, it will use CPU specific instructions to achieve better performance.

  2. It will analyze your execution flow and remove unused loops and branches.

Jitter definitely works well for server-side applications when the application just works, and works, and works.

The only case when you may start thinking about Ngen are Windows Clients. Let’s say, you have huge Windows Client Application It may take long time to startup, because JIT compilation will take too much time and CPU. It is not a problem for server-side applications, but might be a problem for actual users’ software: people do not like waiting for 5 minutes to be able to run an app.

My next article in the series will be all about Ngen. To be continued...

Posted On Tuesday, July 9, 2013 4:15 AM | Comments (8) |

Monday, May 6, 2013

How to change Windows Store App’s Start Page?

 

Finally I have had a chance to start developing Windows 8 applications. I have started with C#/XAML applications. The reason is obvious: I had done a lot of WPF development in the last three years. I have been surprised how easy it is to start building the applications. I have started with Professional Windows 8 Programming: Application Development with C# and XAML and write the code.

Today I’d like to show you one trick which is not obvious for Windows 8 beginners. How can you change Windows 8 Apps’ Start Page?

Let’s create a blank Windows Store Application and show a “Hello Windows 8!” on its Start Screen. Start Screen is MainPage.xaml by default. Open it and add this code.

  1: <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
  2:         <TextBlock Text="Hello Windows 8!"
  3:                    FontSize="40"
  4:                    VerticalAlignment="Center"
  5:                    HorizontalAlignment="Center" />
  6: </Grid>

 

Let’s add another page to the application, e.g. NewStartup.xaml, and show “Hello World!” message there, like this:

  1: <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
  2:         <TextBlock Text="Hello World!"
  3:                    FontSize="40"
  4:                    VerticalAlignment="Center"
  5:                    HorizontalAlignment="Center" />
  6: </Grid>

 

Now we can start with the tricky part. All Windows Store Applications have a manifest file Package.appxmanifest. This is the place where you can set you app’s logos, startup image, default language, etc. You can also specify you application capabilities, e.g. access to a web-cam or Internet. But this is another story.

Manifest

You can see Entry point value on the screen. This class the class which runs when the app is activated. But it is not the same as you app’s Start Page. Let’s take a look what we have there.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.IO;
  4: using System.Linq;
  5: using Windows.ApplicationModel;
  6: using Windows.ApplicationModel.Activation;
  7: using Windows.Foundation;
  8: using Windows.Foundation.Collections;
  9: using Windows.UI.Xaml;
 10: using Windows.UI.Xaml.Controls;
 11: using Windows.UI.Xaml.Controls.Primitives;
 12: using Windows.UI.Xaml.Data;
 13: using Windows.UI.Xaml.Input;
 14: using Windows.UI.Xaml.Media;
 15: using Windows.UI.Xaml.Navigation;
 16: 
 17: // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
 18: 
 19: namespace Blog1
 20: {
 21:     /// <summary>
 22:     /// Provides application-specific behavior to supplement the default Application class.
 23:     /// </summary>
 24:     sealed partial class App : Application
 25:     {
 26:         /// <summary>
 27:         /// Initializes the singleton application object.  This is the first line of authored code
 28:         /// executed, and as such is the logical equivalent of main() or WinMain().
 29:         /// </summary>
 30:         public App()
 31:         {
 32:             this.InitializeComponent();
 33:             this.Suspending += OnSuspending;
 34:         }
 35: 
 36:         /// <summary>
 37:         /// Invoked when the application is launched normally by the end user.  Other entry points
 38:         /// will be used when the application is launched to open a specific file, to display
 39:         /// search results, and so forth.
 40:         /// </summary>
 41:         /// <param name="args">Details about the launch request and process.</param>
 42:         protected override void OnLaunched(LaunchActivatedEventArgs args)
 43:         {
 44:             Frame rootFrame = Window.Current.Content as Frame;
 45: 
 46:             // Do not repeat app initialization when the Window already has content,
 47:             // just ensure that the window is active
 48:             if (rootFrame == null)
 49:             {
 50:                 // Create a Frame to act as the navigation context and navigate to the first page
 51:                 rootFrame = new Frame();
 52: 
 53:                 if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
 54:                 {
 55:                     //TODO: Load state from previously suspended application
 56:                 }
 57: 
 58:                 // Place the frame in the current Window
 59:                 Window.Current.Content = rootFrame;
 60:             }
 61: 
 62:             if (rootFrame.Content == null)
 63:             {
 64:                 // When the navigation stack isn't restored navigate to the first page,
 65:                 // configuring the new page by passing required information as a navigation
 66:                 // parameter
 67:                 if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
 68:                 {
 69:                     throw new Exception("Failed to create initial page");
 70:                 }
 71:             }
 72:             // Ensure the current window is active
 73:             Window.Current.Activate();
 74:         }
 75: 
 76:         /// <summary>
 77:         /// Invoked when application execution is being suspended.  Application state is saved
 78:         /// without knowing whether the application will be terminated or resumed with the contents
 79:         /// of memory still intact.
 80:         /// </summary>
 81:         /// <param name="sender">The source of the suspend request.</param>
 82:         /// <param name="e">Details about the suspend request.</param>
 83:         private void OnSuspending(object sender, SuspendingEventArgs e)
 84:         {
 85:             var deferral = e.SuspendingOperation.GetDeferral();
 86:             //TODO: Save application state and stop any background activity
 87:             deferral.Complete();
 88:         }
 89:     }
 90: }
 91: 

This code is automatically generated by Visual Studio 2012. the answer to our questions is in line 67.

Code

Frame.Navigate method accepts you Start Page’s type and show it when you application has started. What you should do now if to change MainPage to NewStartup, save the file and run the application.

I had been skeptical about Windows 8 as a platform for applications development, but I changed my opinion now. It is great platform and it is really easy to start with. I hope I will have time to write my about my adventures in new Windows world in the future.

Posted On Monday, May 6, 2013 7:15 AM | Comments (5) |

Friday, April 26, 2013

Recovering unallocated space of a USB flash drive.

Today I played with the latest SUSE Linux Live. I had not have a DVD drive and used USB flash drive instead. I wanted to reformat my flash drive, but suddenly found it that it had not been possible. The most of the disk space had been unallocated, and my Windows 8 did not allow me to use it.

Unallocated

Unfortunately Windows does not support Fdisk anymore. But there is another good command line tool to solve this problem. The tool’s name is DiskPart. I would say it is the next generation of Fdisk tool. DiskPart provides you information about your partitions and volumes, allows you to delete and create partitions, extend NTFS volumes, etc.

Let’s remove unallocated space. First of all run Windows command line and type diskpart in the command prompt. Windows will ask you for Administrator permissions to run the tool. Then run list disk command to find your USB flash disk’s number. It should be the same as disk’s number in Computer Management tool. It was 1 in my case. Next you should chose the disk to work with. Type select disk <disk number> command, e.g. select disk 1. The next step is to clean all volumes and partitions on the disk. Use clean command to do that. The last step is to create a primary partition. You can do that using create partition primary command. That’s all. You should be able to format your flash disk now.

This is how I removed unallocated space on my machine:

Microsoft DiskPart version 6.2.9200

Copyright (C) 1999-2012 Microsoft Corporation.
On computer: COMPUTER

DISKPART> list disk

  Disk ###  Status         Size     Free     Dyn  Gpt
  --------  -------------  -------  -------  ---  ---
  Disk 0    Online          298 GB      0 B
  Disk 1    Online         7509 MB  6619 MB

DISKPART> select disk 1

Disk 1 is now the selected disk.

DISKPART> clean

DiskPart succeeded in cleaning the disk.

DISKPART> create partition primary

DiskPart succeeded in creating the specified partition.

DISKPART> exit

Posted On Friday, April 26, 2013 5:19 AM | Comments (174) |

Sunday, April 21, 2013

Using the <base> tag

 

I have an interesting call this morning. One of our customers copy-pasted an email from his email client to our CMS. All links on the page were screwed up, all links on the page had been pointed out to a web-site. The cause of the problem was simple. Email client added the <base> tag to the page to force all links in the email to point out to a third party web-site. It was the first time I had heard about <base> tag.

The <base> tag is used to specify the base URL to use for all relative URLs contained within a page. It means you can use absolute URLs to avoid the issue I had. The tag has two attributes:

  • href. The base URL to be used throughout the document for relative URL addresses.

  • target. A name or keyword indicating the default location to display the result when hyperlinks or forms cause navigation, for elements that do not have an explicit target reference.

You may find very good <base> tag definition on Mozilla Developer Network.

Let’s see two use cases. First of all, I will use the <base> tag without target attribute.

   1:  <!DOCTYPE html>
   2:  <html>
   3:      <base href="http://geekswithblogs.net/ilich/archive/" />
   4:      <ul>
   5:          <li><a href="2013/01/22/wpf-how-to-find-control-location.aspx">WPF: How to Find Control Location.</a></li>
   6:          <li><a href="2012/11/10/wpf-timers.aspx">WPF: Timers.</a></li>
   7:      </ul>
   8:  </html>

All links on the page are pointed to http://geekswithblogs.net/ilich/archive. You will open then in the same browser window.

Now let’s try to use target _blank.

   1:  <base href="http://geekswithblogs.net/ilich/archive/" target="_blank" />

Now you can see the differences. Links pop up in new window.

There is an obvious question. Should I use this tag? There is an obvious answer to this question. It depends… Personally, I would try to avoid using this tag, because it may overcomplicate page maintenance: all relative links will be pointed out to one absolute location. Usually the latest think what a developer will do, when he sees the bug mentioned above,  is to look for a <base> tag. From the other side, <base> tag might be useful in page templates. You can set the base page location and simplify the rest of links in your template. There are pros and cons, and it is up to you either you will use it or not.

Posted On Sunday, April 21, 2013 5:59 PM | Comments (1) |

Powered by: