ASP.NET page change causes an object array in Session to be unable to cast to it's own type? - asp.net

I am storing an array of a custom serializable class in session on my site. When a page on the site changes, suddenly it renders them invalid, and tells me that it can't cast the type to it's own type. I assume the class version numbers are changing or something?!
I'd appreciate avoiding the "don't use session" answers, unless it's a really simple solution. I'm not trying to redesign this whole process.
Unable to cast object of type 'ShipmentPackages[]' to type 'ShipmentPackages[]'.
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.InvalidCastException: Unable to cast object of type 'ShipmentPackages[]' to type 'ShipmentPackages[]'.
Source Error:
Line 21: Else
Line 22: If Not Session("ShipmentList") Is Nothing Then
Line 23: ShipmentList = DirectCast(Session("ShipmentList"), ShipmentPackages()).ToList
Line 24: End If
Line 25: End If

I have seen this message a number of times myself, it is very annoying! As you pointed out, it probably because the assembly version changed. In Asp.Net, when the page changes, the code gets recompiled. Depending on where you put the class will determine if the class gets recompiled with the page or not. I would suggest moving any "model" type classes to a separate project. This will avoid this problem as well as the urge to mix view/controller and model code :).
You can also try serializing the object into session as XML. If you do, you should be able to deserialize it even if the assembly changes, though not if the properties on the object change.
I know you said you didn't want to hear this, but you might also consider not putting objects in the session. This makes it difficult to scale your application if the time ever comes that it is necessary. The sooner you fix this the easier it will be to fix.

A few days ago I got annoyed by this issue too. Alas Brian's first solution will only work as long as you do not need to compile the "model-project" again. If you do that (because of a bugfix, etc.) and update the running application (with users holding their session during the update-process, what is done in my case) you get the exception again :-(!
In my special case the best solution was really easy! I changed "DirectCast" to "TryCast". If the assemblyversion changed and casting fails, trycast will return nothing. In this case, or if I haven't written the dictionary/collection to the session yet, I fetch my data (again) over the database and store afterwards. The next time casting will work ;-)! And another great point, this works also if the interface of the object will change!

Related

MvvmLight ViewmodelLocator StaticResource stops loading

I am consistently experiencing the weirdest thing whenever I use MVVM Light. I create a ViewModelLocator and register in as a static resource in app.xaml:
<viewmodel:WindowsViewModelLocator x:Key="ViewModelLocator" />
Everything works fine, meaning that on launch the static resource is registered, I can use it, and I can see it by going to
App.Current.Resources["ViewModelLocator"]
but then suddenly, randomly, and permanently, this stops working. It has happened to me on every single project, but I'm yet to identify why, as I can't identify the consistent action I did to make it stop working, nor can I figure out any way to revert it back to whatever it was I had when it was working...
the only way to move on is to manually register the resource on startup like this:
if (!Resources.ContainsKey("ViewModelLocator") || Resources["ViewModelLocator"] == null) Resources.Add("ViewModelLocator", new WindowsViewModelLocator());
and finally everything starts working again and usually that's the end of it.
But it happens EVERY SINGLE TIME.
I set a breakpoint in the constructor of the locator and it surely is not being hit... anybody have any idea what I might have possibly done wrong?
EDIT: I finally found the actual exception which was:
A first chance exception of type
'Microsoft.Practices.ServiceLocation.ActivationException' occurred in
GalaSoft.MvvmLight.Extras.DLL
which led me to find the answer which I've posted below. thanks!
It turns out the problem was the order in which I was registering the viewmodels that have dependencies. I have a base ViewModelLocator that initialized the ViewModels, and an inherited ViewModelLocator that contains the Platform-specific code...
In one of the constructors of one of the ViewModels, I was referencing one of the dependent types, which would be registered with a design-time instance. But since this was runtime (which doesn't get registered until it hits the derived platform viewmodellocator) the reference was null.
I moved the dependent code out of the constructor into a more appropriate location and that appears to fix it!
long story short: if you're having this issue, make sure you are initializing everything correctly in the right order and in the right place!

ASP.NET - displaying business layer errors in the presentation layer

Currently in the ASP.NET application I'm developing, basic validations (ie required fields) are being done in the Presentation Layer, using Validators and a ValidationSummary. This is working great for me specifically since the ValidationSummary will display multiple error messages (assuming multiple Validators are set to invalid).
I also have some validations being done in the business layer - due to their complexity (and data service layer reliance) I'd rather not keep them in the presentation layer. However, I'm not sure the best way to send these back to the presentation layer for display to the user. My initial consideration is to send back a List<string> with failed validation messages and then dynamically create a CustomValidator control (since apparently you can only bind one error message to one Validator control) for each error to show in the ValidationSummary when there are any.
I'm assuming I'm not the first one to come across this issue, so I'm wondering if anyone has any suggestions on this.
Thanks!
There are essentially two ways to do this: either by passing back an error code/object from your business layer, or throw out an exception. You can also combine both.
For an example, you can take a look SqlException class. When you send a SQL to SQL Server, it runs a query parser to parse your SQL first. If it sees syntax error, then it will throw out a SqlException and terminate the query. There may be multiple syntax errors in your query. So SqlExeption class has an Errors property that contains a list of errors. You can then enumerate through that list in your presentation layer to format your error message, probably with a CustomValidator.
You can also simply just return the error list without throwing an exception. For example, you can have your function to return a List in case at least one error occurred and return null in case the call was successful. Or you can pass List as an argument into your function. They are all fine, it all depends on which way you feel is more convenient. The advantage of throwing out an exception is it unwinds multiple call frames immediately, so you don’t have to check return value on every level. For example, if function A calls function B , B calls function C, C sees something wrong, then if let C to return an error object (or error code), then B has to have code to check whether C returned an error and pass that error code/value back, A have to check it as well ---- you need to check it on every level. On the other hand, if you just let C to throw an exception, then the code goes straight to the exception handler. You don’t have check return values on every level.

Help with updating vb.net formview using storedprocedure

I have followed this tutorial for the most part to explain what I am doing. http://www.asp.net/data-access/tutorials/creating-a-business-logic-layer-vb
What i need to do is figure out the best way to approach to be able to update my formview. I do not understand what the tutorial is trying to explain to me so i tried it the way i have updated a gridview before. But I am receiving "No parameterless constructor defined for this object." I tried to debug and view the callstack but it does not really tell me much.
I have my sql stored procedure to update which when executed works fine.
I also have another class in which i reference the application details class
applicant.vb
This is the code in order for when you click the view details link on the gridview it passes you off to another page that shows that applicants details it is within the same applicant.vb class
I am trying to update using the following method on the .aspx page but i receive the following error "No parameterless constructor defined for this object."
Memberdetails.aspx
Without knowing which line of code is causing that error, I can't say for sure, however, my guess is that your error is on this line of code.
_applicantadapter = New applicantTableAdapter
Put an open parentheses after applicantTableAdapter to see the different constructor signatures available to you for that type. I bet you'll see none of the options allow no parameters.
That error means that the object type you are trying to instantiate requires that you include parameter(s) (and you are not).

Which exception to throw when not finding a WebForms control which "should" be there

We have a WebForms Control which requires that the ID of another Control implementing ITextControl is provided.
What exception should we throw if there is no control with that ID or a control is found but it's not implementing the interface?
var text = Page.FindControl(TextProviderId) as ITextControl;
if (text == null) {
throw new WhatEverException(...);
...
Should we split it into two cases and throw one exception if there is no control with that ID, and another one if said control does not implement ITextControl? If so, which exceptions should we use then?
If the control should really be there, I would say that your web form is in an invalid state if it is missing, so I would probably go for InvalidOperationException:
The exception that is thrown when a method call is invalid for the object's current state.
This would be applicable to both scenarios; regardless of whether the control is missing or if it does not implement the expected interface, the containing object is in an invalid state.
If this is a scenario that is expected to happen for various reasons (let's say that you are making some tool that others will program against, and this is a situation that they might very well produce), perhaps you should instead create two custom exceptions that make it very clear what is happening and how to correct it (such as ControlNotFoundException and InterfaceNotFoundException or something similar).
ArgumentOutOfRangeException?
Whether or not you should split them up into different exceptions probably depends most on whether or not you think it is likely that anyone will ever want to distinguish the two exceptions in different catch blocks.
Not knowing exactly how this will be used, this seems like the kind of error that should be brought to the developer's attention, where rewriting code to point to the correct file or implement the correct interface is the proper action, rather than implementing a try-catch and give the user friendly error messages. As such, I'd just throw an ArgumentException.

Hiding the stacktrace for an exception returned by a asp.net WebMethod?

I am using methods with the Attribute [WebMethod] in my aspx pages. I don't use any asp.net ajax but jQuery to call these methods and return objects in JSON. This all works fine.
Next I added an authorization check inside the webMethod, if the current user doesn't have access to the feature I need to let the calling JavaScript know.
So I am throwing an AccessViolationException exception which can then be parsed by the OnError callback function in JavaScript. This works too but the exception includes the full StackTrace and I don't want to make this available to the calling client.
What other ways I could use to return an "Access Denied" to the client when the WebMethod returns a business object?
I'm using ASP.Net 3.5SP1 and jQuery 1.32
You can also add a:
customErrors mode="On"/
in your web.config, this will cut away the stack trace and leave you only the exception message
Why propagate errors through the wire? why not use an error response ?
Just wrap your object in a response object wich can contain an error code for status and an error message to present to users.
As suggested by NunFur I changed my approach and rather than throwing an error, I return a 'richer' object.
There are at least two options, the first one would be to encapsulate my business object into a response object with some status properties. I tried this but it makes the JSON more complicated.
So rather than adding a new object I added two properties to my business object, something like ServiceStatus and ServiceMessage. By default these are 200 and '', but can be set by the WebMethod code if anything goes wrong (no access, proper error). In this case they business object will be 'empty' (no data). The JavaScript code then first checks for the ServiceStatus and reacts appropriately.
I add the two fields to all my objects that are returned by WebMethods, even a simple string. They have to implement an Interface with those two properties.
Now I have complete control over that goes over the wire in case something unexpected is happening.
Thanks for the input
I save exceptions for when things go really wrong. (e.g. can't connect to the database)
Either return nothing (null/nill/whatever), or return a false bool value.
Sorry that I don't have a better answer than that...I'll have to keep looking myself.
You could look at SoapException: http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapexception(VS.71).aspx
I'm just not sure, if it will work when it is called from JavaScript. Espeially if it's called with a get-request.
BTW AccessViolationException is to my best knowlegde ment to be thrown when the application is accessing memory it has no access to.
/Asger

Resources