Crystal Report Viewer - Programmatically restricting File Format options - asp.net

In Crystal Reports Viewer (2008) for ASP.Net, when you click on the Export button, the Export dialog shows up with File Format options:
Crystal Reports (RPT)
PDF
Microsoft Excel(97-2003)
Microsoft Excel(97-2003) Data-Only
Microsoft Word (97-2003)
Microsoft Word (97-2003) Editable
Rich Text Format (RTF)
XML
etc..
Does anyone know how to remove some of these options so that end users wouldn't see it?

We've ran into this same issue and ended up rolling our own export page and limited the selection there.
It works great, but I would have expected more from Crystal Reports!

From what I was able to find, you could try to create your own export button option, removing the given button option and adding your own to the asp page. You would need to start by dragging the button onto the page and double clicking it to auto generate the code. From there add the code
crystalReportViewer1.ExportReport ()
Once this code is in it will use the default settings for the export options, however if you want to change the export options within that button then you have to manually code it.
' Declare variables and get the export options.
Dim exportOpts As New ExportOptions()
Dim diskOpts As New DiskFileDestinationOptions()
Dim excelFormatOpts As New ExcelFormatOptions()
exportOpts = Report.ExportOptions
' Set the excel format options.
excelFormatOpts.ExcelTabHasColumnHeadings = true
exportOpts.ExportFormatType = ExportFormatType.Excel
exportOpts.FormatOptions = excelFormatOpts
' Set the export format.
exportOpts.ExportFormatType = ExportFormatType.Excel
exportOpts.ExportDestinationType = ExportDestinationType.DiskFile
' Set the disk file options.
diskOpts.DiskFileName = fileName
exportOpts.DestinationOptions = diskOpts
Report.Export()
MSDN SITE
This link gives you the same code posted above. It show how to do it in Visual Basic code. therefor in your aspx.vb code you would have to manually enter the the types of formats you want.

You might be able to control the export options by removing the export DLLs. Search for crxf_*.dll in the Business Objects\Common\\bin directory.

Refer Below Answer to remove unwanted export Option from Crystal Reports
Display PDF and Excel export options in Crystal Reports?

<asp:ImageButton Width="20px" Height="20px" ID="btnPdf" runat="server"
OnClick="btnExport_Click" ImageUrl="~/Images/PDF.png" AlternateText="Export To PDF" CssClass="AddedButton" />
<asp:ImageButton Width="20px" Height="20px" ID="btnXls" runat="server"
OnClick="btnExport_Click" ImageUrl="~/Images/XLS.png" AlternateText="Export To Excel" />
<asp:ImageButton Width="20px" Height="20px" ID="btnDoc" runat="server"
OnClick="btnExport_Click" ImageUrl="~/Images/DOC.png" AlternateText="Export To Word" />
try this:
<CR:CrystalReportViewer ... HasExportButton="false" HasPrintButton="False" >
<asp:ImageButton Width="20px" Height="20px" ID="btnPdf" runat="server"
OnClick="btnExport_Click" ImageUrl="~/Images/PDF.png" AlternateText="Export To PDF" CssClass="AddedButton" />
<asp:ImageButton Width="20px" Height="20px" ID="btnXls" runat="server"
OnClick="btnExport_Click" ImageUrl="~/Images/XLS.png" AlternateText="Export To Excel" />
<asp:ImageButton Width="20px" Height="20px" ID="btnDoc" runat="server"
OnClick="btnExport_Click" ImageUrl="~/Images/DOC.png" AlternateText="Export To Word" />
C# code:
protected void btnExport_Click(object sender, EventArgs e)
{
// Stop buffering the response
Response.Buffer = false;
// Clear the response content and headers
Response.ClearContent();
Response.ClearHeaders();
try
{
string senderID = ((ImageButton)sender).ID;
if (senderID == "btnPdf")
reportDocument.ExportToHttpResponse(ExportFormatType.PortableDocFormat, Response, true, Page.Title);
else if (senderID == "btnXls")
reportDocument.ExportToHttpResponse(ExportFormatType.ExcelRecord, Response, true, Page.Title);
else if (senderID == "btnDoc")
reportDocument.ExportToHttpResponse(ExportFormatType.WordForWindows, Response, true, Page.Title);
// There are other format options available such as Word, Excel, CVS, and HTML in the ExportFormatType Enum given by crystal reports
}
catch (System.Threading.ThreadAbortException)
{
//The issue has been identified and logged under Problem Report ID
//ADAPT00765364. The error is likely caused because Response.End() is used inside the
//ExportToHttpResponse() method.
//It is a known issue that Reponse.End() causes the thread to abort. This is by design.
//See Microsoft KB312629 Article for more info.
}
catch (Exception ex)
{
//error management
}
}

Apparently a later version (13.0?) adds a AllowedExportFormats property to the CrystalReportViewer class.
I don't have that newer version (I just have 12.0) but apparently something like this is all you need:
int exportFormatFlags = (int)
(CrystalDecisions.Shared.ViewerExportFormats.PdfFormat |
CrystalDecisions.Shared.ViewerExportFormats.ExcelFormat |
// any other desired formats
);
crystalReportViewer1.AllowedExportFormats = exportFormatFlags;

using (ReportClass rptH = new ReportClass())
{
rptH.FileName = #"C:/Report/crJournal.rpt"; //Your rpt file path
// if you put your rpt file on Bin then you need to write only rpt file name
rptH.Load();
rptH.SetDataSource( ds );// Provide Dataset for report : Ds is DataSet
rptH.ExportToDisk(ExportFormatType.Excel, "Give Output file path");
}
This code is defenetly work :

Related

What is the life cycle of an ASP button?

I'm having an issue with the cycle of a page reload and I can't figure it out. I have an ASP button the runs at the server but it has an associated client side click. The client side Javascript is running correctly and returning true to the button click so it is also running. The Javascript makes a modification to the query string on the URL and this is also working. However, in the C# code behind, the query string is not there. Somewhere, I'm missing something.
The HTML link:
<asp:Button ID="btnRunMOReport" class="button-dbg" runat="server"
Text="Run MO Report" OnClick="btnMO_Report_Click"
OnClientClick="return validateCheckBoxesMO()" />
The JavaScript portion:
function validateCheckBoxesMO() {
token='xyz';
let url1 = window.location.href;
if (url1.indexOf("?") > 0) {
url1 = url1.substring(0, url.indexOf("?"));
}
url1 += "?hiddenToken=" + token;
window.location.replace(url1);
return true;
}
The hiddenToken is now represented on the page (?hiddenToken=xyz).
The code behind:
protected void btnMO_Report_Click(object sender, EventArgs e)
{
MailMessage mailtest = new MailMessage();
mailtest.IsBodyHtml = true;
SmtpClient SmtpServertest = new SmtpClient(ConfigurationManager.AppSettings["smtp_server"]);
mailtest.To.Add("Whoever#test123.com");
mailtest.From = new MailAddress("Whoever#test123.com");
mailtest.Subject = Request.QueryString["hiddenToken"];
mailtest.Body = "Whatever";
}
The mail comes just fine but the subject is blank. Somehow, during the page reload cycle, the query string has not yet been set.
If there is a better way to pass data from the JavaScript to the code behind, I'm all ears.
I want to launch another page from the code behind but I need some data that is returned from the JS. The token is actually something I fetch, process the JSON and now I want to make that token available to the code behind for additional information to add to the new URL I am constructing. Probably TMI for this but it is what I am trying to do.
Thanks for your assistance.
Your script isn't working because the browser makes a POST request to submit the form (and __VIEWSTATE) using the action="" attribute of the <form> that WebForms adds to your page.
When your client-script sets window.location it isn't changing how the <form> will behave. You could use your script to append the new querystring value to the <form>'s action="" attribute and this may work, however it will likely fail if the application has request-validation enabled (in which case ASP.NET will reject a tampered form submission).
As you're using WebForms (and you shouldn't be using WebForms in 2021...) you shouldn't try to fight it unless you understand how it all works (I'm not trying to be condescending: it took me years to figure it all out and I've been using WebForms since 2004).
Instead, provide the value through an <asp:HiddenField>:
Change your .aspx markup to this:
<asp:Button runat="server" ID="btnRunMOReport" class="button-dbg"
Text="Run MO Report" OnClick="btnMO_Report_Click"
OnClientClick="return validateCheckBoxesMO()" />
<asp:HiddenField runat="server" ID="superSecretHiddenField" />
Change your client script to this:
function validateCheckBoxesMO() {
const hiddenFieldId = '<%= this.superSecretHiddenField.ClientID %>';
const hiddenField = document.getElementById( hiddenFieldId );
token='xyz';
hiddenField.value = token;
return true; // <-- This is wrong, btw. Instead use `Event.prototype.stopPropagation()` - but that requires the on-click function to be wired-up correctly and I don't remember the specifics other than that WebForms *doesn't* do things correctly (not out-of-spite, but because WebForms predates the standardisation of client-script events).
}
And your code-behind to this:
protected void btnMO_Report_Click(object sender, EventArgs e)
{
MailMessage mailtest = new MailMessage();
mailtest.IsBodyHtml = true;
SmtpClient SmtpServertest = new SmtpClient(ConfigurationManager.AppSettings["smtp_server"]);
mailtest.To.Add("Whoever#test123.com");
mailtest.From = new MailAddress("Whoever#test123.com");
mailtest.Subject = this.superSecretHiddenField.Value;
mailtest.Body = "Whatever";
}
As noted, a button post back will in general over-write the url that you change. Unless you actually do a navigation client side that is caused by the js, then it will not persist.
So, on the most simple level, just drop in a text box, or hidden field, and put the value you need/want into that hidden textbox or field.
So, client side? Markup?
You can use this:
<asp:Button ID="Button1" runat="server" Text="Delete"
OnClientClick="SetHidden();"/>
<asp:HiddenField ID="HiddenField1" runat="server" ClientIDMode="Static"/>
<br />
<script>
function SetHidden() {
hField = document.getElementById('HiddenField1');
hField.value = 'zoo';
return true;
}
</script>
So in above, we set our value in js to zoo, and of course we do return true. If we return false then the asp.net button code server side will not run - so we can control this, or even say pop up a confirm dialog and return true/false based on that to control if the server side code behind will run.
Server side, code behind? You can now use this:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Debug.Print(HiddenField1.Value)
End Sub
So the above is easy, clean. You can also use a text box, and set the style="display:none", but a hidden field is just as well and easy.

What is going on with the ajax AutoCompleteExtender?

This really is bizarre. I'm trying to implement the AutoCompleteExtender using a database. I enter the first character, let's say 'T' into the textbox, and the drop down results panel shows all of the page's source code (client side rather than server side), one character per line as seen in the image.
AutoComplete Results Screenshot
Incidentally, Google Chrome displays this straight away, while IE has a good think about it, saying localhost is not responding because it's running a long script.
If I then select any one of those characters it then displays the correct results beginning with 'T', though replaces the character I typed with whatever I selected.
I pulled the code from a tutorial on codeproject.com and apart from changing the textbox ID and a bit of ADO so it points to my database, it's identical.
I'll include the code. What's going wrong?
Now for some reason, it's not letting me post the code, regardless of how I format, but this is what I used. AutoComplete With DataBase and AjaxControlToolkit
It is very hard to give answer without seeing the code... try this
<asp:TextBox ID="txtSearchKey" runat="server" Width="350" AutoPostBack="true" OnTextChanged="txtSearchKey_TextChanged" />
<asp:TextBoxWatermarkExtender ID="weSearchKey" runat="server" Enabled="True" TargetControlID="txtSearchKey" WatermarkText="Search by Name" WatermarkCssClass="watermark" />
<asp:AutoCompleteExtender ServiceMethod="YourWebMethod" MinimumPrefixLength="3" CompletionInterval="100" EnableCaching="false" CompletionSetCount="10" TargetControlID="txtSearchKey" ID="searchExtender" runat="server" FirstRowSelected="false" OnClientItemSelected="GetSelectedId" CompletionListCssClass="completionList" CompletionListItemCssClass="listItem" CompletionListHighlightedItemCssClass="itemHighlighted" CompletionListElementID="divCompletionListElement" />
<input type="hidden" id="hdnSelectedId" name="hdnSelectedId" value="" />
Have a javascript method to ensure selected item is captured
function GetSelectedId(source, eventArgs) {
var selectedId = eventArgs.get_value();
var e = document.getElementById('hdnSelectedId');
if (e) {
e.value = selectedId;
}
}
Create a WebMethod in your back end code that is configured in ServiceMethod property of AutoCompleteExtender
[ScriptMethod()]
[WebMethod]
public static List<string> YourWebMethod(string prefixText, int count)
{
var totalRecords = 0;
var searchResults = <<get your results here into a list or whatever container>>
//I used DataTable as a container here for searchResults
if (searchResults.Rows.Count == 0)
return new List<string>() { "No result found" };
//Create a List from your search results and return it
List<string> items = new List<string>();
foreach (DataRow searchResult in searchResults.Rows)
items.Add(AutoCompleteExtender.CreateAutoCompleteItem(searchResult["Name"].ToString(), searchResult["BuilderID"].ToString());
return items;
}

.NET Ektron 8.6 : How to use value in query string for Ektron Server Control MenuModel (TreeFilter.Id)

I am trying to pass a value that the ektron:MenuModelSource.TreeFilter control will use to generate the given menu. I am able to get the value from the query string
I am working on the menu solution and am stumped on what to do differently.
I am needing to set the Id for the TreeFilter property of the web server control below:
<ektron:MenuModelSource ID="menuModelSource2" runat="server">
<TreeFilter Id="355" Depth="1" />
</ektron:MenuModelSource>
I am passing a query string that looks like: ?top=355&side=375&low=123 .This way an id can be passed for each menu to be used by each designated TreeFilter on a page.
I am also able to pull in that info to the code behind file and convert it to an int for use by the TreeFilter (all of the following code is done in PageLoad):
string sideIdstr = Request.QueryString["side"];
int sideId = Convert.ToInt32(sideIdstr);
menuModelSource2.TreeFilter.Id = sideId;
However, the MenuModelSource.TreeFilter is still rendering the 355 menu rather than the 375 menu.
I can “verify” that the id has indeed been changed to 375 by using the following:
Response.Write("<h1>" + menuModelSource2.TreeFilter.Id + "</h1>");
… which shows 375 on the page.
What should I be doing instead to get the TreeFilter to use the id from the query string?
Someone suggested trying DataBind() on the server controls, but I still get the same results. Here is my current code:
protected void Page_Load(object sender, EventArgs e)
{
Ektron.Cms.API.Content.Content ContentAPI = new Ektron.Cms.API.Content.Content();
Page.Title = ContentAPI.GetContent(PageHost1.PageID).Title;
string sideIdstr = Request.QueryString["side"];
int sideId = Convert.ToInt32(sideIdstr);
menuModelSource2.TreeFilter.Id = sideId;
menuModelSource2.DataBind();
menuView2.DataBind();
Response.Write("<h1>" + menuModelSource2.TreeFilter.Id + "</h1>");
}
…and my markup is this…
<ektron:MenuModelSource ID="menuModelSource2" runat="server">
<TreeFilter Id="355" Depth="1" />
</ektron:MenuModelSource>
<ektron:MenuView ID="menuView2" runat="server" ModelSourceID="menuModelSource2">
<ListTemplate>
<ul id="menunav" runat="server" class="unstyled subnav">
<asp:PlaceHolder ID="listPlaceholder" runat="server" />
</ul>
</ListTemplate>
<ItemTemplate>
<li <%# ((Eval("Type").ToString().ToLower() == "submenu")) ? #" class=""subnav""" : #" class=""menuitem""" %>>
<asp:HyperLink ID="nodeLink" runat="server" Text='<%# Eval("Text") %>' NavigateUrl='<%# Utility.getNavigateUrl( Eval("NavigateUrl") ) %>' />
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</li>
</ItemTemplate>
</ektron:MenuView>
If anyone has a better way of doing this such as using the Ektron Framework API I would be open to that as well.
After updating the parameters of the Model source you need to call LoadData on the model source. However that method is not public, so you need to do this trick using reflection to call the method.
menuModelSource2.GetType().GetMethod("LoadData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy).Invoke(menuModelSource2, new object[] { });
This is documented at reference.ektron.com See the aspx.cs tab. It's at the bottom.

to validate file extension for uploading file in firefox

I created the upload page using with FileUpload server control. And I used regular expression validator to validate file extension.
<asp:FileUpload ID="AttachmentUpload" CssClass="text" size="58" Width="376px" IE:Width="385px" runat="server"/>
<asp:RequiredFieldValidator SetFocusOnError="true"
ID="AttachmentUploadRequire"
runat="server"
ControlToValidate="AttachmentUpload"
Display="None"
ErrorMessage="Please select a file to attach."/>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
runat="server"
ErrorMessage="The selected file type is not allowed!"
ControlToValidate="AttachmentUpload"
Display="None"
ValidationExpression="^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))+(\.[mM][pP]3|\.[mM][pP][eE][gG]|\.[sS][wW][fF]|\.[dD][oO][cC]|\.[tT][xX][tT]|\.[jJ][pP][gG]|\.[jJ][pP][eE][gG]|\.[pP][nN][gG]|\.[xX][lL][sS]|\.[pP][dD][fF]|\.[gG][iI][fF]|\.[pP][pP][tT])$"/>
It is Ok for chrome and IE but not Ok for firefox. How can I solve it?
Firefox only supplies the file name information, not its path information. Your regular expression parses for path information, thus it fails.
I believe that other non-IE browsers also only send the file name. The purpose is to protect the user's privacy (i.e.: you could obtain their system username if the file was stored under My Documents in windows).
Consider using a Javascript function and call it on your form button's OnClientClick event. This approach works for all browsers:
function checkFileExtension() {
var filePath = document.getElementById('AttachmentUpload').value;
var validExtension = 'xml';
var ext = filePath.substring(filePath.lastIndexOf('.') + 1).toLowerCase();
if (ext.toLowerCase() == validExtension)
return true; //xml file is valid
alert('The file extension ' + ext.toUpperCase() + ' is not allowed!');
return false; //all other types of files are not valid
}

Update an image control as soon as a file is selected in File Upload control in ASP.NET

I have an image control and a file upload control in .NET 2.0 (VS.NET 2008) form. As soon as user selects an image file in the file upload control, i want the image to appear in the image control of the form. What would be the way to do this ?
(The only event File Upload seems to support is 'OnChange' and i don't know enough javascript to update Image1.URL based on content of FileUpload).
Thanks,
Chak.
You need to upload Asynchronously , and you could try AJAX AsyncFileUpload and this is what you are looking...
http://asp.net-informations.com/ajax/ajax-AsyncFileUpload.htm
Are you looking for a kind of preview? You can only show the image to the user after the file has been uploaded. I'm pretty sure the user has to actively do so (otherwise you could try to read the entire filesystem from the browser)
I think this is a good example:
http://www.codeproject.com/KB/ajax/AJAXUpload.aspx
this is a good starting point too:
http://www.eggheadcafe.com/community/aspnet/2/10204276/how-to-display-image-when-upload-image.aspx
or here:
http://www.eggheadcafe.com/community/aspnet/2/10236947/image-upload-and-display.aspx
updated
protected void Button4_Click(object sender, EventArgs e)
{
string strExtn;
string strpostedfile;
strpostedfile = fileuploading.PostedFile.FileName;
strExtn = System.IO.Path.GetExtension(strpostedfile);
strExtn = strExtn.ToLower();
string strEx = Path.GetExtension(fileuploading.PostedFile.FileName).ToLower();
String filename = Path.GetFileName(fileuploading.FileName);
filename = filename.Remove(filename.Length - strEx.Length);
fileuploading.SaveAs(Server.MapPath("~/Photos/") + filename);
uploadImage.ImageUrl = "~/Photos/" + filename;
}
Page:
<asp:FileUpload ID="fileuploading" runat="server" />
<asp:Button ID="Button4" runat="server" onclick="Button4_Click" Text="Button" />
<br />
<asp:Image ID="uploadImage" runat="server" />

Resources