ASP.NET web service returns 400 - asp.net

If I de-serialize the data and an error occurs later in the update process (for example: the change fails to meet a database constraint). I'd like to report something useful to the end user here, but it looks like .NET is swallowing the error. Any idea why?
<WebInvoke(method:="POST", uriTemplate:="changes", bodyStyle:=WebMessageBodyStyle.Bare)>
Public Function PostChanges(body As Stream) As String
Try
' This returns 500 Server Error (with wrapped exception)
'Throw New Exception("TEST")
Dim data As String = ""
Using reader As New StreamReader(body)
data = reader.ReadToEnd()
End Using
' This returns 400 Bad Request
'Throw New Exception("TEST")
' Code handling data removed (no error if exceptions are removed)
Catch ex As Exception
Throw New WebFaultException(Of DisplayError)(New DisplayError(ex.Message, ex.StackTrace), Net.HttpStatusCode.InternalServerError)
End Try

Apparently, StreamReader disposes of its underlying Stream object which causes problem if your code has the temerity to break normal flow by raising an exception.
So, now I'm using OperationContext.Current.RequestContext.RequestMessage.ToString, which has its own problems but at least I'm not choosing between messed up error logging or a resource leak.

Related

Having issue with View State on ASP.net Website

I have just moved my dev website to a new computer and have got most of the web pages working. The only web pages that won't work are pages that have a postback. I know the code works fine which is why I think it is being caused by the view state. I keep getting this error:
Value cannot be null.
Parameter name: inputString
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: inputString
This is the function where the error is being thrown:
Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object
'Dim vState As String = Me.Request.Form("__VSTATE")
PageStatePersister.Load()
Dim vState As String = PageStatePersister.ViewState.ToString
If Not vState Is Nothing Then
Dim bytes As Byte() = System.Convert.FromBase64String(vState)
bytes = vioZip.Decompress(bytes)
Dim format As New LosFormatter
Return format.Deserialize(System.Convert.ToBase64String(bytes))
Else
Return Nothing
End If
End Function
Does anyone know why it is giving me this error? I can't find what is being passed to it that might be null, but I know the code itself does not pass any null values. Let me know if you need any more information. Thank you in advance for your responses.
Check if the page has EnableViewState="true"
And verify the site-wide setting in web.config -
<pages enableViewState="true" enableViewStateMac="true" ... />

Correct way of streaming a CSV of unknown size from memory

I have a database that has a table with just over 2 million records of about 20 columns. The user is able to query the database and limit the number of records returned so the recordset may be from 1 to 2 million.
As it is tabular information I want to send the data as a CSV. I'm using a StreamWriter to write the data to memory and once the file is complete I'm sending it as an HttpResponseMessage. My code is below, and it works fine as long as I don't run out of memory. Is there a way for me to stream the file as it's being processed so that the memory used is minimal?
<HttpGet, Route("api/records/export")>
Public Function ExportRecords() As HttpResponseMessage
Dim stream As New MemoryStream
Dim writer As New StreamWriter(stream)
writer.WriteLine("")
' Processing of data here
writer.WriteLine("""Write Data to MemoryStream"")
writer.Flush()
stream.Position = 0
Dim result As New HttpResponseMessage(HttpStatusCode.OK)
result.Content = New StreamContent(stream)
result.Content.Headers.ContentType = New Headers.MediaTypeHeaderValue("text/csv")
result.Content.Headers.ContentDisposition = New Headers.ContentDispositionHeaderValue("attachment") _
With {.FileName = "I" & Format(Date.Now, "yyMMdd") & ".csv"}
Return result
End Function
I've read on StackOverflow answers to questions such as Returning binary file from controller in ASP.NET Web API but these all deal with streaming a web response from a file stored on disk and not from memory.
As the comment on my question suggested I used PushStreamContent to stream the contents of my database to the browser in CSV format. I also made it asynchronous to get even more performance out of the export.
There is an important limitation with using PushStreamContent to stream content to the client from the server. Since the 200 OK header is sent first before anything is streamed, the response doesn't know ahead of time if there's going to be an error in the results as they're returned. If something goes wrong while the results are being sent, the client will just see a generic network error on its end. It's up to the server to log any error so that you can check server logs to find the specific error.
Here is the code for PushStreamContent that I used (the error checking is removed for brevity).
Dim result As HttpResponseMessage = New HttpResponseMessage(HttpStatusCode.OK) With {
.Content = New PushStreamContent(Async Function(outStream, httpContent, context)
Dim writer As StreamWriter = New StreamWriter(outStream)
Await writer.WriteLineAsync("""Header 1"",""Header 2"",""Header 3""")
For Each item In returnItems
Await writer.WriteLineAsync("""" & item.Col1.ToString & """,=""" & item.Col2.ToString & """,=""" & item.Col3.ToString & """")
Await writer.FlushAsync()
Next
outputStream.Close()
End Function)}
result.Content.Headers.ContentType = New Headers.MediaTypeHeaderValue("text/csv")
result.Content.Headers.ContentDisposition = New _
Headers.ContentDispositionHeaderValue("attachment") With {.FileName = "MyCSV.csv"}
Return result

Custom Exception with Entity Framework and Repository Pattern

I am following this Asp .Net tutorial as a guide:
http://www.asp.net/web-forms/tutorials/continuing-with-ef/using-the-entity-framework-and-the-objectdatasource-control-part-2-adding-a-business-logic-layer-and-unit-tests
I have created a custom error to prevent duplicate records on insert and update
Public Class DuplicateAgencyException
Inherits Exception
Public Sub New(ByVal message As String)
MyBase.New(message)
End Sub
End Class
I have created a validation method that checks for duplication on insert or update:
Public Sub ValidateAgencyName(ByVal agency As agency_temp)
If Not IsNothing(agency) Then
Dim duplicateAgency As agency_temp = AgencyRepository.GetAgencyByName(agency.agency_name).FirstOrDefault()
If Not IsNothing(duplicateAgency) AndAlso duplicateAgency.agency_id <> agency.agency_id Then
Throw New DuplicateAgencyException(String.Format("Agency: {0} already exists.", duplicateAgency.agency_name))
End If
End If
End Sub
I run a unit test to insert a record, and purposefully insert a duplicate, and it throws the correct error. Now I need to handle this error with the ObjectDataSource that displays this data, such as OnInserted and OnUpdated, but I can't even get to that point. When I insert a record, I get the error assistant telling me that DuplicateAgencyException was unhandled by user code. Do I need a try...Catch there? (I did try that to no avail).
I believe you need to wrap your exception within the methods referenced by the events you mention in a try catch block as you suggest. You should wrap the existing code like so
MethodName(params)
《
try 《 /// existing code
》
catch (ExceptionType ex) 《
/// error handling code
》
》
If you post your event handling code and the aspx i can be more specific. Please excuse any errots wrote this on my phone.

How to customize InnerException.Message for System.Data.UpdateException in ASP.NET

First of all thanks for taking the time to read through my post. I have a question that may be a newbie piece of cake for some.
I am adding data to a database table using Entity Framework. When adding a duplicate Primary Key I get an exception in InnerException.Message that reads "Violation of PRIMARY KEY constraint 'PK_StudentID'. Cannot insert duplicate key in object 'dbo.Students'. The statement has been terminated. "
However, what I want to do is to rephrase this error message for the end user, but also save this exact message with the table name and column name to my logs for later. Essentially, I want to rephrase the error message to "You cannot have a duplicate entry for Student Identification Number. Please enter a new value."
How can I do this?
I have tried to inherit from System.Data.UpdateException and put an if check to see what the innerexception.message reads, and then change it accordingly. That did not work.
Thanks,
I think this will do what you want.
Try
'your code
Catch ex As Exception
'store the ex.Message where you want
Throw New Exception("Your custom message here.")
End Try
Example:
Private Sub uiFunction()
Dim errorMessage As String
Try
'a call to a BLL function/sub that could cause an exception
Catch ex As Exception
errorMessage = ex.Message() 'ex.Message() = "Your custom message."
End Try
End Sub
Public Sub BLLFunction()
Try
'run your code that could cause an exception
Catch ex As Exception
Throw New Exception("Your custom message.")
End Try
End Sub

Why do we get "Path not found" error while accessing vb code from classic asp page?

Could you please give your suggestions to the below problem:
I am working on a old project which was developed using traditional ASP and VB6.0.
I have registered the dll in component services. After creating the object in first line (in the code snippet below), when trying to call Login() method, it is giving the "Path not found" warning/error and I am not able to continue executing it further.
Thanks in advance for your consideration and help...also please let me know if you need more information...
SET objSecurity = Server.CreateObject( Application("APP_CLASS") & "Security" )
SET ox = new XMLTool
userID = uCase(userID)
dataXML = ""
IF objSecurity.Login( sessXML, userID, pwd, datXML ) Then
ox.LoadXML dataXML
..........
..........
"Path not found" is usually an IO exception. Does the objSecurity.Login() method read or write any data to a file or directory that does not exist? What is happening inside the objSecurity.Login() method?
Alternately, is there another "benign" method of the objSecurity object that you can call to verify that the object lives? Something like:
Dim sTest As String = objSecurity.Version()
or
Dim sTest As String = objSecurity.Name()
or even
Dim bExists As Boolean = (objSecurity IsNot Nothing)
I know that .ToString() didn't exist in VB6, but that's the idea.
Let's narrow down the problem to either objSecurity object itself, or something inside the .Login() method.

Resources