Wednesday, June 11, 2008

Resize and position Javascript popup

In many of my project i came across the situation where i had to open a popup with a particular size and position the popup in the middle of the window. I was sending the height and width parameter in the window.open() funtion parameter. But many times i had to add some extra controls in that page which needs the increase of the popup size. I was problemetic for me to goback to the parent page and find the javascript which is opening the popup and change.
So i decided to control the size from the popup itself. And i used
window.resizeTo(width,height) function for that purpose and called it on body onLoad event.
But what about positioning the popup?
For both the pubpose to solve i wrote a function resizeAndPositionWindow() which takes height and width as parameter and positions the popup in the middle of the window. Below is the function...
function resizeandPositionWindow(width,height)
{
window.resizeTo(width,height);
var scrW = 1024, scrH = 768;
var popW=width,popH=height;
if (document.all document.layers) {
scrW = screen.availWidth;
scrH = screen.availHeight;
}
else
{
try
{
scrW = window.screen.availWidth;
scrH = screen.availHeight;
}
catch(e){}
}
if(document.all)
{
popW=document.body.clientWidth;
}
else
{
if(document.layers)
{
popW=window.innerWidth;
popH=window.innerHeight;
}
else
{
try
{
popW=window.innerWidth;
popH=window.innerHeight;
}
catch(e){alert('Exception');}
}
}
var x,y;
x=(scrW-popW)/2-13;
y=(scrH-popH)/2;
window.moveTo(x,y);
}

By default it is assumed that the screen resolution of the user is 1024X768. Then it determines the actual height.
I used the above funtion to make a function which will take a int parameter as gap between the popup and computer screen and will make the popup which will have that length in top,bottom,left and right.
function resizeAccordingToScreenSize(gap)
{
var scrW = 1024, scrH = 768;
if (document.all document.layers) {
scrW = screen.availWidth;
scrH = screen.availHeight;
}
else
{
try
{
scrW = window.screen.availWidth;
scrH = screen.availHeight;
}
catch(e){}
}
var gapPx=0;
try
{
gapPx=parseInt(gap)*2;
}
catch(e){alert("Wrong value for gap.")}
resizeAndPositionWindow(scrW-gapPx,scrH-gapPx);
}

Tuesday, June 3, 2008

Use stored credential for report created by c# code

In my current project i have created an interface through which admin can generate the report he wants from any of the table (or combination of tables) from any DB in the server. The interface is generating the xml Report Defination (rdl) and publishing it with the reporting service web service.
Now the problem came with the datasource of the report. When i publish the report it was showing the username and password input box in the report viewer. If i put those it was running beautifulluy. But it was not what i wanted. None of us will bother to give the UID and password everytime. Here is the sample of code i used to generate the report

static int zIndex = 1;
string serverName = "localhost";
string reportVirtualPath = "LocalReportServer";
string parentFolder = "QuoteReports";
string dataSetName = "DSSOP";
string dataSourceName = "DynamicDataSource";
string parTabName = "bodyTable";

void deployReport(string reportName, string reportDefination)// reportDefination is the xml rdl
{
ReportingService2005 rs = new ReportingService2005();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
byte[] byteRDL;
System.Text.UTF8Encoding encoder = new UTF8Encoding();
byteRDL = encoder.GetBytes(reportDefination);
Property[] rsProperty = new Property[10];
//Property property = new Property();
Warning[] warnings;
try
{
warnings = rs.CreateReport(reportName, "/" + parentFolder, true, byteRDL, null);
}
catch (System.Web.Services.Protocols.SoapException ex)
{
tdMessage.InnerHtml = "Exception in publiching report.
" + ex.Message + "
";
return;
}
}

I was using report-specific datasource with authentication. My sample datasource section of the RDL is below
<datasource name="Personal">
<?xml:namespace prefix = rd /><rd:datasourceid>1a234378-11f1-4dc0-bc74-91df6d7d94f7</rd:datasourceid>
<connectionproperties>
<dataprovider>SQL</dataprovider>
<connectstring>Data Source=SODC42\SQLEXPRESS;Initial Catalog=SOP;UID=sa;password=123456;</connectstring>
</connectionproperties>
</datasource>

Though i was putting the connection string with UID and password, still it was showing the textboxes for username and password.
After a lot of google i found that reporting service uses two connection strings 1) one for connection to the report server 2) another for connection the report server to the databse (In mycase the both of report server and DB server is same express version in localhost). The connection string supplied in the RDL is for the first purpose and the second connection information is stored with the DataSource information in the ReportServer DB.
Then i open the report with the reportmanager (http://localhost/reports) and edit the report. In the editor i found the datasources link where i saw the "Credentials supplied by the user running the report" radio is selected. I canged the selection to "Credentials stored securely in the report server" and gave the desired credentials. Then i saw the report is not showinf the text boxes.
Now it was clear that the problem is with the DataSource not with the RDL. Then i went with the idea of using SharedDataSource and attach it with the report. While deploying the report i was checking if the shared datasource is already existing. If not then create it. Here is the code for creating the shared datasource.

DataSourceDefinition def = new DataSourceDefinition();
def.CredentialRetrieval = CredentialRetrievalEnum.Store;
def.ConnectString = ReportConnection.GetConnection("SOP").ConnectionString;
def.Enabled = true;
def.EnabledSpecified = true;
def.Extension = "SQL";
def.ImpersonateUser = false;
def.ImpersonateUserSpecified = true;
def.WindowsCredentials = false;
def.UserName = "sa";
def.Password = "123456";
rs.CreateDataSource(dataSourceName, dataSourcePath, true, def, null);
rs.SetDataSourceContents(dataSourcePath + "/" + dataSourceName, def);

Note:Before creating you have to check whether it already exists of not. And also the folder structure.
The rdl for datasource :
<DataSources>
<DataSource Name="DynamicDataSource">
<DataSourceReference>/Data Sources/DynamicDataSource</DataSourceReference>
</DataSource>
</DataSources>
Now the report is running fine.
But still there was something hitting in my mind. Why i shall use SharedDataSource? I shall use report specific datasource. But how?
After some days lots of RnD s i found it. It is totally my assumtion. I have no idea how far it is true. But it works.
The report specific datasources you have to keep in a folder "Data Sources" in the same directory as the report and then only the report can use it. So i created the datasource in the report folder's "Data Sources" folder. And so far it is running.

Download Sample Project
For information about the project refer to my other post
Generate Your Dynamic Report Through Reporting Service