Crystal Report on ASP C# application & postback issues - c#

I have a webform with a single button and one crystal report viewer. Crystal report is based on a MS SQL stored procedure & designed using a connection that uses SQL Server authentication.
What I have noticed that, if I call the method for showing the report within the page load, my crystal repot loads perfectly. However, if I trigger the report load through the button click (Which is a must for me to accept parameters for the report at deployment) the below happens:
Crystal report parameters are prompted (Which doesn't occur when report is loaded without a postback).
After the 1st page being loaded, 2nd page navigation prompts for database login. Without providing the login details (usually the password only), cannot go ahead. This logon prompt is only applicable to 2nd page of the report.
To circumvent the situation, I created a new connection with integrated security & postback stopped asking for the parameters and database login. Unfortunately, I cannot use integrated security for deploying the application & pry for a proper solution or workaround.
Fearing the worst, I already have RDLC report designed with the same requirements, however, I see that I have better formatting options like drawing lines over the sub reports to split columns when Crystal Report is used.
Here is what I have I tried until now
ASP page
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="c2.aspx.cs" Inherits="CrystalTest.c2" %>
<%# Register Assembly="CrystalDecisions.Web, Version=13.0.4000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Show Report" OnClick="Button1_Click" />
<CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server" AutoDataBind="False" GroupTreeImagesFolderUrl="" Height="1202px" ReportSourceID="CrystalReportSource1" ToolbarImagesFolderUrl="" ToolPanelView="None" ToolPanelWidth="200px" Width="1104px" />
</div>
</form>
</body>
</html>
Code behind
using CrystalDecisions.CrystalReports.Engine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CrystalTest
{
public partial class c2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//ShowReport();
}
private void ShowReport()
{
ReportDocument oRpt = new ReportDocument();
oRpt.Load(Server.MapPath(#"~/CrystalReport2.rpt"));
oRpt.SetParameterValue(0, 2020);
oRpt.SetParameterValue(1, 1);
oRpt.SetParameterValue(2, "3");
oRpt.SetParameterValue(3, "1");
oRpt.SetParameterValue(4, "1");
CrystalReportViewer1.Visible = true;
CrystalReportViewer1.ReportSource = oRpt;
//oRpt.SetDatabaseLogon("sa", "password", "RT04", "menass");
oRpt.DataSourceConnections[0].SetConnection("RT04", "menass", true);
}
protected void Button1_Click(object sender, EventArgs e)
{
ShowReport();
}
}
}

I have referred the following threads from different websites and was able develop a simple solution.
1.https://www.c-sharpcorner.com/forums/crystal-reports-asking-for-database-login-credentials
2.https://forums.asp.net/post/1797759.aspx
All I needed was to pass the logon information back to the report viewer once after POSTBACK happens. Example as below:
ASP Page
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="c3.aspx.cs" Inherits="CrystalTest.c3" %>
<%# Register Assembly="CrystalDecisions.Web, Version=13.0.4000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Print Button" OnClick="Button1_Click" />
<CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server" AutoDataBind="false" />
</div>
</form>
</body>
</html>
Code Behind
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using CrystalDecisions.Web;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CrystalTest
{
public partial class c3 : System.Web.UI.Page
{
public ReportDocument oRpt;
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
ConnectionInfo myConnectionInfo = new ConnectionInfo();
myConnectionInfo.ServerName = "RT04";
myConnectionInfo.DatabaseName = "MenaSS";
myConnectionInfo.UserID = "sa";
myConnectionInfo.Password = "password";
SetdblogonforReport(myConnectionInfo);
}
}
private void SetdblogonforReport(ConnectionInfo myConnectionInfo)
{
//throw new NotImplementedException
TableLogOnInfos mytableloginfos = new TableLogOnInfos();
mytableloginfos = CrystalReportViewer1.LogOnInfo;
foreach (TableLogOnInfo myTableLogOnInfo in mytableloginfos)
{
myTableLogOnInfo.ConnectionInfo = myConnectionInfo;
}
}
private void ShowReport()
{
if (!IsPostBack | Session["Report"] == (default))
{
oRpt = new ReportDocument();
oRpt.Load(Server.MapPath(#"~/CrystalReport2.rpt"));
oRpt.SetParameterValue(0, 2020);
oRpt.SetParameterValue(1, 1);
oRpt.SetParameterValue(2, "9");
oRpt.SetParameterValue(3, "1");
oRpt.SetParameterValue(4, "1");
Session.Add("Report", oRpt);
}
else
{
oRpt = (ReportDocument)Session["Report"];
}
CrystalReportViewer1.ReportSource = oRpt;
oRpt.SetDatabaseLogon("sa", "password", "RT04", "menass");
}
protected void Button1_Click(object sender, EventArgs e)
{
ShowReport();
}
}
}
This solution is good enough for sub reports also, as all the authentications are taken care by the single logon call using the method SetdblogonforReport.
Hope this helps few others out there.

I've a better solution & not deleting the previous one because it does deal with the postback when page_load method is present in a page. The below answer (which is recommended by SAP) is the one I am currently using for my project.
Resolving this requirement using "Session" and "page_init" as suggested. Please note, my application need to collect many inputs from the end user before generating the report & many of the text inputs have Autopostback set as true. Everytime the autopostback happens, Crystal Report refreshes, hence I recommend using as less possible Autopostback enabled input fields with your web form.
Sample ASP page
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="c4.aspx.cs" Inherits="CrystalTest.c4" %>
<%# Register Assembly="CrystalDecisions.Web, Version=13.0.4000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Print Report" OnClick="Button1_Click" />
<CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server" AutoDataBind="true" />
</div>
</form>
</body>
</html>
and the code behind (copied from a crude test form, please make sure that you follow the coding standards recommended). Please note, this sample doesn't have "page_load" method, hence if you have specific situations where page_load is required, you will have to adapt much tedious approaches or clicking the button to generate the report should be redirected to a page where you have only the report.
using CrystalDecisions.CrystalReports.Engine;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CrystalTest
{
public partial class c4 : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
if (IsPostBack)
{
CrystalReportViewer1.ReportSource = (ReportDocument)Session["Report"];
}
}
private void ShowReport1()
{
string ConnectionString = ConfigurationManager.ConnectionStrings["menass"].ToString();
using (SqlConnection con = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("GETMONTHSALARY", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#pProcessYear", SqlDbType.Int).Value = 2020;
cmd.Parameters.Add("#pProcessMonth", SqlDbType.Int).Value = 1;
cmd.Parameters.Add("#pProcessSection", SqlDbType.VarChar).Value = "9";
cmd.Parameters.Add("#pProcessSite", SqlDbType.VarChar).Value = "1";
cmd.Parameters.Add("#pProcessCatg", SqlDbType.VarChar).Value = "1";
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "SalaryDT");
ReportDocument oRpt = new ReportDocument();
oRpt.Load(Server.MapPath(#"~/dataset/CrystalReport1.rpt"));
oRpt.DataSourceConnections.Clear();
oRpt.SetDataSource(ds);
oRpt.Subreports[0].SetDataSource(FillOverTime());
CrystalReportViewer1.Visible = true;
CrystalReportViewer1.ReportSource = oRpt;
Session["Report"] = oRpt;
}
}
}
private DataSet FillOverTime()
{
string ConnectionString = ConfigurationManager.ConnectionStrings["menass"].ToString();
using (SqlConnection con = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("GetEmployeeOverTime", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#pEmployeeCode", SqlDbType.VarChar).Value = DBNull.Value;
cmd.Parameters.Add("#pProcessYear", SqlDbType.Int).Value = 2020;
cmd.Parameters.Add("#pProcessMonth", SqlDbType.Int).Value = 1;
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds1 = new DataSet();
adapter.Fill(ds1, "OverTimeDT");
return ds1;
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
ShowReport1();
}
}
}

Related

Crystal Report requires server login for ASP.NET / C# app

I have several Crystal Reports that run fine in Visual Studio.
They also run fine after publishing the reports except that they ask for a server login when running (after publishing). How do you code it so that it provides the login information instead of asking the user?
Report returns data correctly if user enters the login info. C# code (aspx.cs) is shown below and html (aspx) is below that.
I show C# code that I added to try and fix the login issue as well (of course it does not fix the issue).
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Data;
using System.Web.Security;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using System.Data.SqlClient;
using CrystalDecisions.CrystalReports;
using CrystalDecisions.ReportSource;
using CrystalDecisions.Web;
namespace Productivity_ASPWeb
{
public partial class OPReport : System.Web.UI.Page
{
ReportDocument rpt = null;
private void Page_Init(object sender, EventArgs e)
{
if (Session["rpt"] != null)
{
ReportDocument rpt = new ReportDocument();
rpt.Load(Server.MapPath("bin/Outpatient_Report_Card.rpt"));
OPReportViewer.ReportSource = rpt;
Session["rpt"] = rpt;
OPReportViewer.ReportSource = (ReportDocument)Session["rpt"];
OPReportViewer.DataBind();
}
}
}
}
I tried adding the following code but it did not make a difference:
// Set DataSource to your DataTable
rpt.SetDataSource("OutPatient_Report_Card");
OPReportViewer.EnableDatabaseLogonPrompt = false;
ConnectionInfo crConInfo = new ConnectionInfo();
TableLogOnInfo crTblLogonInfo = new TableLogOnInfo();
crConInfo.ServerName = "mssql";
crConInfo.DatabaseName = "Productivity";
crConInfo.UserID = "dwoodard";
crConInfo.Password = "Cordova234";
OPReportViewer.LogOnInfo[0].ConnectionInfo = crConInfo;
// crDoc1 is your ReportDocument
// dtDataTable is your DataTable
// after setting the DataSource apply Logon credentials to each table in ReportDocument
Tables CrTables = rpt.Database.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in CrTables)
{
crTblLogonInfo = CrTable.LogOnInfo;
crTblLogonInfo.ConnectionInfo = crConInfo;
CrTable.ApplyLogOnInfo(crTblLogonInfo);
}
rpt.Refresh();
// rpt.SetDatabaseLogon("WebProductivityUser", "N0tbutton55!", "mssql", "Productivity");
Here is the html:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="OPReport.aspx.cs" Inherits="Productivity_ASPWeb.OPReport" %>
<%# Register assembly="CrystalDecisions.Web, Version=13.0.4000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" namespace="CrystalDecisions.Web" tagprefix="CR" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Outpatient Report</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<CR:CrystalReportViewer ID="OPReportViewer" runat="server" AutoDataBind="True" Height="1202px"
ReportSourceID="CrystalReportSource1" ToolPanelWidth="200px" Width="1104px" HasRefreshButton="True"
ShowAllPageIds="True" GroupTreeStyle-BackColor="Aqua" GroupTreeStyle-BorderColor="#336600"
GroupTreeStyle-BorderStyle="Dashed" HasPrintButton="False" ReuseParameterValuesOnRefresh="True"
ToolbarStyle-BackColor="#003399" ToolbarStyle-BorderColor="#996633" ToolbarStyle-BorderStyle="Double"
GroupTreeImagesFolderUrl="" ToolbarImagesFolderUrl="" />
<CR:CrystalReportSource ID="CrystalReportSource1" runat="server">
<Report FileName="Outpatient_Report_Card.rpt">
</Report>
</CR:CrystalReportSource>
</div>
</form>
</body>
</html>

SQL Server 2008 R2, Crystal Report and asp.net issue

I am using SQL Server 2008 R2, Crystal Report 13 and Microsoft Visual Studios 2010 Ultimate,
I have created a crystal report and a crystal report viewer but on execution of the software once i click the command button it does not show the report in the viewer, even i cant see the empty report also. i cant see anything no viewer nor and empty report which is strange, i do not understand what is the error. here is my code in the button.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
using System.IO;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.ReportSource;
using CrystalDecisions.Reporting;
public partial class _Default : System.Web.UI.Page
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["CS"].ConnectionString);
ReportDocument rptLog = new ReportDocument();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
con.Open();
// SqlCommand cmd = new SqlCommand("stpLogReport", con);
// cmd.CommandType = CommandType.StoredProcedure;
string Query = "Select * from tblLogReport";
SqlDataAdapter da = new SqlDataAdapter(Query, con);
DataTable ds = new DataTable();
da.Fill(ds);
rptLog.Load(Server.MapPath("CrystalReport.rpt"));
rptLog.SetDataSource(ds);
rptLog.SetParameterValue("UserName", "zaigham.ali");
CrystalReportViewer1.ReportSource = rptLog;
CrystalReportViewer1.RefreshReport();
CrystalReportViewer1.DataBind();
con.Close();
}
}
// This is a connection string in web.config
<add name="CS" connectionString="Data Source=LAPTOP-JOV450P2;Initial Catalog=DATABASE;Persist Security Info=True;User ID=sa;Password=abcvfddde" providerName="System.Data.SqlClient"/>
Check if you peoples can help me.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%# Register assembly="CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" namespace="CrystalDecisions.Web" tagprefix="CR" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Show Report"
onclick="Button1_Click" />
<CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server"
AutoDataBind="True" GroupTreeImagesFolderUrl="" HasRefreshButton="True"
Height="1202px" ToolbarImagesFolderUrl="" ToolPanelView="ParameterPanel"
ToolPanelWidth="200px" Width="903px" />
</div>
</form>
</body>
</html>

Couldn't load type 'HomePage.aspx.cs'

I am implementing a small website that will take input from the user and interact with a database in c# but the problem is that the code behind (the code in the .aspx.cs file) doesn't read any element in the .aspx file,though I did assigned the inherit attribute in the directive of the .aspx file to be the .aspx.cs file .
This is the HomePage.aspx file
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="HomePage.aspx.cs" Inherits="HomePage.aspx.cs" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lbl_username" runat="server" Text="Username: "></asp:Label>
<asp:TextBox ID="txt_username" runat="server"></asp:TextBox>
<asp:Label ID="lbl_password" runat="server" Text="Password: "></asp:Label>
<asp:TextBox ID="txt_password" runat="server" TextMode="Password"></asp:TextBox>
<asp:Button ID="btn_login" runat="server" Text="Login" onclick="login" />
</div>
</form>
</body>
</html>
This is the HomePage.aspx.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
public partial class HomePage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void login(object sender, EventArgs e)
{
string connStr = ConfigurationManager.ConnectionStrings["MyDbConn"].ToString();
SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand("loginProcedure", conn);
cmd.CommandType = CommandType.StoredProcedure;
string username = txt_username.Text;
string password = txt_password.Text;
cmd.Parameters.Add(new SqlParameter("#username", username));
SqlParameter name = cmd.Parameters.Add("#password", SqlDbType.VarChar, 50);
name.Value = password;
// output parm
SqlParameter count = cmd.Parameters.Add("#count", SqlDbType.Int);
count.Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
if (count.Value.ToString().Equals("1"))
{
Response.Write("Passed");
}
else
{
Response.Write("Failed");
}
}
}
I am getting that error couldn't load type 'HomePage.aspx.cs' , So how can I do handle such event ?
You only need the class name not the full file name for the inherits attribute
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="HomePage.aspx.cs" Inherits="HomePage" %>
The Inherits property should not contain the file extension. Here's what the Microsoft documentation says about the Inherits property:
Inherits
Defines a code-behind class for the page to inherit. This can be any
class derived from the Page class. This attribute is used with the
CodeFile attribute, which contains the path to the source file for the
code-behind class. The Inherits attribute is case-sensitive when using
C# as the page language, and case-insensitive when using Visual Basic
as the page language.
So the CodeBehind (or CodeFile for Web Site projects) attribute should have the file path, while the Inherits attribute contains just the class name. Try replacing Inherits="HomePage.aspx.cs" with Inherits="HomePage", including the namespace if applicable.

Generating asp controls with mark up in db [duplicate]

How do I generate the controls in a div based on the markup defined in a SQL Server database? Is it possible? If yes, then how? Can anyone give me resources?
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication2.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Literal ID="lit" runat="server" ClientIDMode="Static" Mode="Transform"></asp:Literal>
</div>
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection _newConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand storedProcedure = new SqlCommand("sp_getMarkup", _newConnection);
storedProcedure.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(storedProcedure);
_newConnection.Open();
da.Fill(ds);
_newConnection.Close();
DataTable dt = ds.Tables["Table"];
string s = (from str in dt.AsEnumerable()
where str.Field<int>("Id").Equals(1)
select str.Field<string>("elemMarkup")).SingleOrDefault().ToString();
this.lit.Text = s;
}
}
}
In the database I have stored string as
<asp:CheckBox ID="chk" runat="server" ClientIDMode="Static" />
Now the problem is the control is rendered on page but is not visible. I can see it in view source.
Can anyone help me?
You can use ParseControl which accepts a string and create controls on the fly.
The drawback is if server code is in the string, it will not be executed. In addition, you need to attach event manually such as button click events.
For example,
<script runat="server">
// This server code will not be executed
</script>
Here is another SO question using jquery ajax to load info from database
I would recommend having some type of sanitizing intermediary; otherwise you are opening yourself up to cross-site scripting (XSS) issues.
You could use a placeholder on a page like so:
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</div>
</form>
</body>
And in your code behind, you could have several checks (all of which contain SQL statements querying the data in the database). The database could contain a field containing component names such as checkbox, button (various other controls). This saves you storing markup in the database fields..
Very rough representation of how the code would look like..
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// SQL Code here
// Datatable code here
// End of DataTable code
// Beginning of IF blocks
If (DataTable.Rows.Count > 0) {
If (your check != "checkbox") {
this.PlaceHolder1.Controls.Add(new Button(){
Text = "Added"}
}
}
// More if statements here
);
}
}
Alternatively if you insist on storing asp markup in the database, then you could just feed the asp markup into the placeholder using a loop (if there are more than one rows in your database)

How to generate asp.net control using markup in database

How do I generate the controls in a div based on the markup defined in a SQL Server database? Is it possible? If yes, then how? Can anyone give me resources?
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication2.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Literal ID="lit" runat="server" ClientIDMode="Static" Mode="Transform"></asp:Literal>
</div>
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection _newConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand storedProcedure = new SqlCommand("sp_getMarkup", _newConnection);
storedProcedure.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(storedProcedure);
_newConnection.Open();
da.Fill(ds);
_newConnection.Close();
DataTable dt = ds.Tables["Table"];
string s = (from str in dt.AsEnumerable()
where str.Field<int>("Id").Equals(1)
select str.Field<string>("elemMarkup")).SingleOrDefault().ToString();
this.lit.Text = s;
}
}
}
In the database I have stored string as
<asp:CheckBox ID="chk" runat="server" ClientIDMode="Static" />
Now the problem is the control is rendered on page but is not visible. I can see it in view source.
Can anyone help me?
You can use ParseControl which accepts a string and create controls on the fly.
The drawback is if server code is in the string, it will not be executed. In addition, you need to attach event manually such as button click events.
For example,
<script runat="server">
// This server code will not be executed
</script>
Here is another SO question using jquery ajax to load info from database
I would recommend having some type of sanitizing intermediary; otherwise you are opening yourself up to cross-site scripting (XSS) issues.
You could use a placeholder on a page like so:
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</div>
</form>
</body>
And in your code behind, you could have several checks (all of which contain SQL statements querying the data in the database). The database could contain a field containing component names such as checkbox, button (various other controls). This saves you storing markup in the database fields..
Very rough representation of how the code would look like..
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// SQL Code here
// Datatable code here
// End of DataTable code
// Beginning of IF blocks
If (DataTable.Rows.Count > 0) {
If (your check != "checkbox") {
this.PlaceHolder1.Controls.Add(new Button(){
Text = "Added"}
}
}
// More if statements here
);
}
}
Alternatively if you insist on storing asp markup in the database, then you could just feed the asp markup into the placeholder using a loop (if there are more than one rows in your database)

Categories