Direct Printing in Asp.net - asp.net

In my application,i need to print my reports without converting to pdf or any other formats.I need to print the record as soon as the user clicks the print button.i have used the following code.but unfortunately,this is not direct print,it is converting into pdf and then printing.converting to pdf takes a lot of time which makes our life dreadful.Below is my code.Please help....
Private Sub imgPrint_Click(ByVal sender As System.Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles imgPrint.Click
'Function to open connection and table
Dim dt As DataTable
Dim SQLString As String = TKSUCSearchChild.SQLWhereClause
Try
'dt = GetTableData("View_Item", SQLString, SQLOrderByClause)
'dt = Your DataTable
oRpt = New YourReportName
oRpt.SetDataSource(dt)
View_PickingSlip.ReportSource = oRpt
Dim exp As ExportOptions
Dim req As ExportRequestContext
Dim st As System.IO.Stream
Dim b() As Byte
Dim pg As Page
pg = View_PickingSlip.Page
exp = New ExportOptions
exp.ExportFormatType = ExportFormatType.PortableDocFormat
exp.FormatOptions = New PdfRtfWordFormatOptions
req = New ExportRequestContext
req.ExportInfo = exp
With oRpt.FormatEngine.PrintOptions
.PaperSize = PaperSize.PaperLegal
.PaperOrientation = PaperOrientation.Landscape
End With
st = oRpt.FormatEngine.ExportToStream(req)
pg.Response.ClearHeaders()
pg.Response.ClearContent()
pg.Response.ContentType = "application/pdf"
ReDim b(st.Length)
st.Read(b, 0, CInt(st.Length))
pg.Response.BinaryWrite(b)
pg.Response.End()
dt.Dispose()
Catch ex As Exception
ShowError(ex.Message)
End Try
End Sub

There is no way to accomplish this becuase you can't issue commands to the client from the server to make the computer print, it just doesn't work that way. There are ways to print using pdf's, but it is not very elegant and you stated you don't want to use pdfs...other than that I think you would have write some kind of browser plugin that would have to be installed on the machine that needs to print.

#AGoodDisplayName is mostly right. However, you don't give details of your environment - if you're building an intranet-based application, it is possible to have the server print directly to a printer, if that printer is accessible to the server.
There will be issues with security, and it will be a problem if you have many users with many printers, but it is possible.

Another option (if you have a captive audience with IE/Windows) is to run an "agent" process on the client machine. You can then have a web page "poke" that process with the data to be printed. In modern IE, the easiest way to do this is with APP (asynchronous pluggable protocols).
Without the "benefit" of IE/Windows, you're pretty much stuck with PDF.

Related

How can I store the data in memory and use by the other Button click event to display the data?

Here is the code, but the datatable is NULL in ButtonExport click event, how can i pass the DataTable to Sub ButtonExport_Click ? I dont want to store in Session as the data is too big
Here is the class clsGlobalVarriable
Public Class clsGlobalVariable
Private _gdt As DataTable
Public Property globalDataTable As DataTable
Get
Return _gdt
End Get
Set(ByVal value As DataTable)
_gdt = value
End Set
End Property
End Class
Here is the From frmTest code:
Public Class frmTest
Inherits System.Web.UI.Page
Private gdt As New clsGlobalVariable
Protected Sub ButtonInactivePC_Click(sender As Object, e As EventArgs) Handles ButtonInactivePC.Click
Try
Dim func As New clsFunction
Dim command As String = "Get-ADComputer -Filter { OperatingSystem -NotLike '*Windows Server*'} -Property * | select Name, CanonicalName, operatingSystem, LastLogonDate, Description, whenChanged | Where {($_.LastLogonDate -lt (Get-Date).AddDays(-90)) -and ($_.LastLogonDate -ne $NULL)}"
Dim arr As New ArrayList
arr.Add("Name")
arr.Add("CanonicalName")
arr.Add("operatingSystem")
arr.Add("LastLogonDate")
arr.Add("whenChanged")
arr.Add("Description")
gdt.globalDataTable = func.PSObjectToDataTable(command, arr)
Me.GridView1.DataSource = gdt.globalDataTable
Me.GridView1.DataBind()
Catch ex As Exception
Me.LabelDebug.Text = "Button Click" + ex.Message
End Try
End Sub
Protected Sub ButtonExport_Click(sender As Object, e As EventArgs) Handles ButtonExport.Click
Dim func As New clsFunction
Dim dt As New DataTable
dt = (DirectCast(Me.GridView1.DataSource, DataTable))
Me.LabelDebug.Text = "Global Data Table Count = " & dt.Rows.Count
End Sub
When working with webpages that show data to the user, and the user takes some action on that data you either need to store the data somewhere in their computer, your computer (the server) or rely on the fact that it's still stored in the computer you got it from. As a process you have undertaken:
You generate a grid from querying AD
You send the grid to the customer's computer - so it's stored there as a visual representation (and maybe also ViewState)
It's still stored in AD, where you got it
You could also store it locally on the server somehow - Session, DB, text file, whatever
Decide on which of these to use when the user clicks Export:
Dig it out of the viewstate or other data that was sent to the user - for this you'll have to code things up so it comes back from the user
Get it out of AD again - simple to do; you did it once and sent it to the user in HTML. Getting it again and sending it to the user again this time as a CSV isn't really any different from the first time you did it
Restore it from wherever you kept it on the server
Choose the first if your user is going to modify the data or choose to export only some of it - the data he sends back to you should indicate which bits he wants exporting.
Choose the second option if you want an easy life, and it's just a straight export, no editing or subset of data. Write one method that gets the data out of AD and then use it in either place, one to form HTML/fill a grid, in the other to send a file to the user. Don't get hung up on "well I already got this data once, it's a waste to get it again" - no-one writes a Login Page and thinks "i'll only ever look up a user from the DB once, then get the server to remember the login data forever more and use it next time there is a login request" - they store the data in the db, and look it up every time there is a login. DBs store data and perform the same queries over and over again. This is no different
You probably wouldn't choose the third option, for reasons already mentioned
I decided to use alternative for the Excel Export, i am not going to pass the DataTable, instead i pass the GridView to the Export to Excel function
Add the following sub right after Page_load, this is to avoid the GridView error
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
End Sub
Here is the Code:
Public Sub ExportFromGridview(ByVal gv As GridView, ByVal response As HttpResponse
response.Clear()
response.Write("<meta http-equiv=Content-Type content=text/html;charset=utf-8>")
response.AddHeader("content-disposition", "attachment;filename=" & Now & ".xls")
response.ContentType = "application/vnd.xls"
Dim stringWrite As System.IO.StringWriter = New System.IO.StringWriter()
Dim htmlWrite As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(stringWrite)
gv.RenderControl(htmlWrite)
response.Write(stringWrite.ToString())
response.End()
End Sub

Can't share isolated storage file between applications in different app pools

I've got various web apps (containing WCF services) in IIS under the default website. As long as they are all running in the same app pool they can access a shared isolated storage file no problem.
However, once I move them to different app pools I get "System.IO.IsolatedStorage.IsolatedStorageException: Unable to create mutex" when one tries to access a file created by another. They are all running under NetworkService user. I tried GetUserStoreForAssembly and GetMachineStoreForAssembly all with the same result. Any ideas why they couldn't use a shared file?
I made sure to close the stream and even dispose it in case one was holding onto it, but I am running a simple test where one service writes it, then another tries to read from it later, and it always fails.
Also, I am accessing the isolated store from a signed assembly.
Does anybody have any ideas?
Here is the code:
Private Sub LoadData()
Dim filename = FullFilePath(_fileName)
Dim isoStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForAssembly()
' Tried GetMachineStoreForAssembly, same failure
isoStorage.CreateDirectory(ROOT_DIRECTORY)
If (isoStorage.GetFileNames(filename).Length = 0) Then
Return
End If
Dim stream As Stream = New IsolatedStorageFileStream(filename, FileMode.OpenOrCreate, isoStorage)
If stream IsNot Nothing Then
Try
Dim formatter As IFormatter = New BinaryFormatter()
Dim appData As Hashtable = DirectCast(formatter.Deserialize(stream), Hashtable)
Dim enumerator As IDictionaryEnumerator = appData.GetEnumerator()
While enumerator.MoveNext()
Me(enumerator.Key) = enumerator.Value
End While
Finally
stream.Close()
stream.Dispose()
stream = Nothing
End Try
End If
End Sub
Public Sub Save()
Dim filename = FullFilePath(_fileName)
' Open the stream from the IsolatedStorage.
Dim isoFile As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForAssembly()
' Tried GetMachineStoreForAssembly, same failure
Dim stream As Stream = New IsolatedStorageFileStream(filename, FileMode.Create, isoFile)
If stream IsNot Nothing Then
Try
Dim formatter As IFormatter = New BinaryFormatter()
formatter.Serialize(stream, DirectCast(Me, Hashtable))
Finally
stream.Close()
stream.Dispose()
stream = Nothing
End Try
End If
End Sub
Looks like it was a trust issue.
After adding the assembly accessing the isolated storage file to the gac it magically worked as everything in the gac has full trust set automatically.
This works for me, but it might not always be an option to do this for other solutions. Check out the .NET Framework caspol utility if this is the case.
Hope this helps somebody! It was a huge pitafor me.

Crystal Report convert to PDF (Error The logon to the database failed. ((0x8004100f)))

In my application I have some code to convert to PDF. In debug mode all is good and working but when I test it on then server I keep getting the logon to the database failed. I have no idea why I get the error becase the login and password are 100% ok.
tried 2 ways for the server of sending the report
SetCrystalReportFilePath(Server.MapPath("~/MemberPages/Report.rpt"))
SetPdfDestinationFilePath(Server.MapPath("~/MemberPages/Report_" & Report & ".pdf"))
SetRecordSelectionFormula("{Report.Report_id} =" & ID)
Transfer()
SetCrystalReportFilePath("C:\inetpub\wwwroot\Werkbon.rpt")
SetPdfDestinationFilePath("C:\inetpub\wwwroot\Werkbon_" & werkbonnr & ".pdf")
SetRecordSelectionFormula("{werkbon.werkbon_id} =" & werkbonnr)
Transfer()
Dim ConInfo As New CrystalDecisions.Shared.TableLogOnInfo
Dim oRDoc As New ReportDocument
Dim expo As New ExportOptions
Dim sRecSelFormula As String
Dim oDfDopt As New DiskFileDestinationOptions
Dim strCrystalReportFilePath As String
Dim strPdfFileDestinationPath As String
Public Function SetCrystalReportFilePath(ByVal CrystalReportFileNameFullPath As String)
strCrystalReportFilePath = CrystalReportFileNameFullPath
End Function
Public Function SetPdfDestinationFilePath(ByVal pdfFileNameFullPath As String)
strPdfFileDestinationPath = pdfFileNameFullPath
End Function
Public Function SetRecordSelectionFormula(ByVal recSelFormula As String)
sRecSelFormula = recSelFormula
End Function
Public Function Transfer()
oRDoc.Load(strCrystalReportFilePath)
oRDoc.RecordSelectionFormula = sRecSelFormula
oDfDopt.DiskFileName = strPdfFileDestinationPath
expo = oRDoc.ExportOptions
expo.ExportDestinationType = ExportDestinationType.DiskFile
expo.ExportFormatType = ExportFormatType.PortableDocFormat
expo.DestinationOptions = oDfDopt
oRDoc.SetDatabaseLogon("databasename", "password")
oRDoc.Export()
End Function
Crystal is very particular when swapping in and out connection information (especially with sub-reports if you have any). It's always been a sore spot that they haven't really made any better over the years. I have a blog entry I've shared that has extension methods I created (in VB.Net) to easily load and swap in new connections (typically I use ADO for the connection in the report). The extension methods can be found in this link (and below is an example of how to use them, ignore the System.Diagnostics line if you're using this from ASP.NET). Hope this helps.
http://www.blakepell.com/Blog/?p=487
Using rd As New ReportDocument
rd.Load("C:\Temp\CrystalReports\InternalAccountReport.rpt")
rd.ApplyNewServer("serverName or DSN", "databaseUsername", "databasePassword")
rd.ApplyParameters("AccountNumber=038PQRX922;", True)
rd.ExportToDisk(ExportFormatType.PortableDocFormat, "c:\temp\test.pdf")
rd.Close()
End Using
System.Diagnostics.Process.Start("c:\temp\test.pdf")

BackgroundWorker for YouTube DirectUpload in VB.NET?

I'm trying to implement a direct upload of videos on my server to YouTube. When a user adds a video, it gets copied to YouTube.
The user action of adding the video should begin the upload process, which could take a while. The form, even an asynchronous form, should not sit there and wait for this to happen. It should just begin and allow the user to move on, trusting that it is being taken care of in the background.
To allow this, I am attempting to use system.threading.backgroundworker. My hope is that the process would begin, and the web app would move on. It's not. It's hanging, whether it's an asynchronous or full postback, and waiting for the upload to finish before returning and updating the lblmsg.text.
Is there a different way I should be going about this, so the user can initiate the upload procedure and not wait around for it to complete? Here is my code so far:
Sub up_load(s As Object, e As EventArgs)
Dim worker As BackgroundWorker = New BackgroundWorker
worker.WorkerReportsProgress = True
worker.WorkerSupportsCancellation = True
AddHandler (worker.DoWork), AddressOf begin_upload
'call this and move on?
worker.RunWorkerAsync()
lblmsg.Text = "Successfully initiated upload"
End Sub
Sub begin_upload(s As Object, e As DoWorkEventArgs)
Dim request As New YouTubeRequest(settings)
Dim vidupload As New Video()
vidupload.Title = "My Big Test Movie"
vidupload.Tags.Add(New MediaCategory("Nonprofit", YouTubeNameTable.CategorySchema))
vidupload.Keywords = "church, jesus"
vidupload.Description = "See the entire video"
vidupload.YouTubeEntry.Private = False
vidupload.YouTubeEntry.setYouTubeExtension("location", "Downers Grove, IL")
vidupload.YouTubeEntry.MediaSource = New MediaFileSource("c:\users\greg\test3.asf", "video/x-ms-wmv")
Dim createdVideo As Video = Request.Upload(vidupload)
End Sub
You might want to look into the Task Parallel Library for adding multithreading to your code. Given the code that you provided:
Add this import statement
Imports System.Threading.Tasks
And replace all backgroundworker logic with this simple statement:
Dim uploadTask As Task = Task.Factory.StartNew(Sub()
Dim request As New YouTubeRequest(settings)
Dim vidupload As New Video()
vidupload.Title = "My Big Test Movie"
vidupload.Tags.Add(New MediaCategory("Nonprofit", YouTubeNameTable.CategorySchema))
vidupload.Keywords = "church, jesus"
vidupload.Description = "See the entire video"
vidupload.YouTubeEntry.Private = False
vidupload.YouTubeEntry.setYouTubeExtension("location", "Downers Grove, IL")
vidupload.YouTubeEntry.MediaSource = New MediaFileSource("c:\users\greg\test3.asf", "video/x-ms-wmv")
Dim createdVideo As Video = request.Upload(vidupload)
End Sub)
Now you have the uploadTask uploading your video in the background and your UI thread will be free to process other code. It does get a bit more complicated if you want cancellation and progress reporting, but the link at the top should get you started.

ASP.NET Page_Load runs twice due to Bitmap.Save

I have created an VB.NET page to record views for ads and will call page from img src.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim insert_number As Integer = 0
Dim ad_id As Integer = 0
If Request.QueryString("adid") Is Nothing Then
ad_id = 0
Else
If Not Integer.TryParse(Request.QueryString("adid"), ad_id) Then
ad_id = 0
End If
End If
Dim connectStr As String = System.Configuration.ConfigurationManager.AppSettings("connectStr").ToString()
Dim myconnection As SqlConnection = New SqlConnection(connectStr)
Dim mySqlCommand As SqlCommand
myconnection.Open()
Try
mySqlCommand = New SqlCommand("sp_record", myconnection)
mySqlCommand.CommandType = CommandType.StoredProcedure
mySqlCommand.Parameters.AddWithValue("#record_id", ad_id)
insert_number = mySqlCommand.ExecuteNonQuery()
Catch ex As Exception
End Try
myconnection.Close()
Dim oBitmap As Bitmap = New Bitmap(1, 1)
Dim oGraphic As Graphics = Graphics.FromImage(oBitmap)
oGraphic.DrawLine(New Pen(Color.Red), 0, 0, 1, 1)
'Response.Clear()
Response.ContentType = "image/gif"
oBitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif)
'oBitmap.Dispose()
'oGraphic.Dispose()
End Sub
Unless I comment oBitmap.Save line, the code runs twice and it makes two inserts (store prcoedure runs twice) to Database.
I have tried AutoEventWireup = "true" and "false" at #PAGE. "true" runs code twice, "false" did not do anything (no error) and did not give any output as well.
I have also tried following version of creating 1pixel image output but it did run twice as well (it requires aspcompat=true in #PAGE part):
'Response.ContentType = "image/gif"
'Dim objStream As Object
'objStream = Server.CreateObject("ADODB.Stream")
'objStream.open()
'objStream.type = 1
'objStream.loadfromfile("c:\1pixel.gif")
'Response.BinaryWrite(objStream.read)
Any ideas are welcome.
You may want to do an onload function for the image to see why it's being called a second time. I'm guessing that it's getting loaded somewhere in the preload and then being called (.Save) during the page load as well and that's why you're seeing the double entry.
If you are trying to get unique page loads, you may want to try putting the oBitmap.Save line within a check for postback like this within the page load:
If Page.IsPostback = False Then
'Bitmap Code Here
End If
And see if that fixes it for you.
If you're loading data from a database, you'll want to make sure that it also is within that PostBack check (because a. you're loading the data twice and b. it can cause these double postbacks in some circumstances).
Edit: Wanted to edit code section to include all bitmap code, not just the save.
Not sure about the specifics, but that is a lot of code within in Page_Load function.
Generally, the way I would solve this type of problem is to have some sort of page arguments that you can check for in order to do the correct things. Either add some get/post parameters to the call that you can check for or check things like the Page.IsPostBack.
I realize this is an old post but I had an similar issue where the page was firing twice on the postback. I found several posts sugesting what is being dicusses here. However, what corrected my issue was setting the page directive property AutoEventWireup=false at the page level.
Here is a good article How to use the AutoEventWireup attribute in an ASP.NET Web Form by using Visual C# .NET that helped me solve this.
Hope this helps!
Risho

Resources