【问题标题】:Crystal Report on ASP C# application & postback issues关于 ASP C# 应用程序和回发问题的 Crystal Report
【发布时间】:2020-12-19 03:59:44
【问题描述】:

我有一个带有一个按钮和一个水晶报表查看器的网络表单。 Crystal 报表基于 MS SQL 存储过程并使用使用 SQL Server 身份验证的连接进行设计。 我注意到,如果我调用在页面加载中显示报告的方法,我的水晶报告会完美加载。但是,如果我通过单击按钮触发报告加载(我必须在部署时接受报告的参数),则会发生以下情况:

  1. 提示水晶报表参数(在没有回发的情况下加载报表时不会出现这种情况)。
  2. 加载第 1 页后,第 2 页导航提示登录数据库。如果不提供登录详细信息(通常只提供密码),则无法继续。此登录提示仅适用于报表的第 2 页。

为了规避这种情况,我创建了一个具有集成安全性的新连接,并且回发停止询问参数和数据库登录。不幸的是,我无法使用集成安全性来部署应用程序并寻求适当的解决方案或解决方法。

担心最坏的情况,我已经设计了具有相同要求的 RDLC 报表,但是,我发现我有更好的格式化选项,例如在使用 Crystal Report 时在子报表上画线以拆分列。

这是我到目前为止所尝试的

ASP 页面

<%@ 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>

后面的代码

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();
        }
    }
}

【问题讨论】:

    标签: c# asp.net crystal-reports


    【解决方案1】:

    我参考了来自不同网站的以下主题,并能够开发出一个简单的解决方案。

    1.https://www.c-sharpcorner.com/forums/crystal-reports-asking-for-database-login-credentials 2.https://forums.asp.net/post/1797759.aspx

    我所需要的只是在 POSTBACK 发生后将登录信息传回报表查看器。示例如下:

    ASP 页面

    <%@ 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>
    

    代码背后

    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();
            }
    
        }
    
    }
    

    此解决方案对于子报告也足够好,因为所有身份验证都由使用方法 SetdblogonforReport 的单一登录调用处理。

    希望这对其他人有所帮助。

    【讨论】:

      【解决方案2】:

      我有一个更好的解决方案而不是删除前一个解决方案,因为它确实在页面中存在 page_load 方法时处理回发。以下答案(由 SAP 推荐)是我目前用于我的项目的答案。

      按照建议使用“Session”和“page_init”解决此要求。请注意,我的应用程序需要在生成报告之前收集来自最终用户的许多输入,并且许多文本输入都将 Autopostback 设置为 true。每次自动回发发生时,Crystal Report 都会刷新,因此我建议在您的 Web 表单中尽可能少地使用启用自动回发的输入字段。

      示例 ASP 页面

      <%@ 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>
      

      以及后面的代码(从粗略的测试表格中复制而来,请确保您遵循推荐的编码标准)。请注意,此示例没有“page_load”方法,因此如果您有需要 page_load 的特定情况,您将不得不采用非常繁琐的方法或单击按钮生成报告应重定向到您拥有的页面只有报告。

      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();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 2010-11-22
        • 2011-09-16
        • 1970-01-01
        • 2016-08-26
        • 2014-08-14
        • 1970-01-01
        相关资源
        最近更新 更多