Optional Invalid Query String Variables - asp.net

This is a somewhat philosophical issue. I have a .net (but could be any platform) based helper library that parses query string values. Take for example a variable that returns an Int32: my framework has an option that specifies whether this value is required or optional. If it is required but not provided, the framework throws an exception. If it is optional and not specified, it returns a null.
Now an edge case has come up based on users hacking (in a good way) our urls. If they specify a variable with either an invalidly formatted Int32 ("&ID=abc") or provide the variable but not specify a value ("&id="), should the framework throw an exception or should it return a null?
Part of me feels that invalid variables or formats should return a null. It might be valid to argue that even if the parameter is optional, an invalidly formatted query string or value should still throw an exception.
Thoughts?

Since this is philophical ...
On something like an ID, I would agree with Shawn that it is a 404, especially if you are thinking in terms of state. There is no object, so not found. But, ID may not tie directly to a resource in all cases.
If the item is truly optional, a null is okay. But optional should mean "if present it makes the call more specific" in this case and there should always be a fallback. I don't see this in ID, unless the ID is keyed to an optional part of the page.
In the long run, I think you should look at the business reason for the page and what each variable means.

I believe that if a variable is optionaly, providing the variable but not specifying the value is equivalent to ommitting the variable itself. In this case, returning null seems OK.
However, providing an invalidly formatted value ought to cause an Exception, since the intent was to provide a value. In this case the user ought to be notified through some sort of validation mechanism.

A HttpException of 404 (Not Found). Your web application framework should know how to catch these errors and redirect to the proper page.
This is actually a not found error because the resources that the ID is pointing to does not exist.

I suspect there's no "right" answer to your question. If I were a developer using your library, I would expect/hope that the public API would include in its code comments, a description of how the function behaves when the URL param includes bad (wrong type) data.
You might also be able to craft your public API to get the best of both worlds: .NET seems to have adopted the "Parse" / "TryParse" approach in many places. If I'm the caller and I want the function to throw if given invalid data, I call Parse(). If I don't want it to throw, I call TryParse(). In my opinion, that is a nice pattern to follow with your API as well.

Related

Kusto's `parse_json` doesn't work on custom dimensions

I'm hoping to be able to analyze structured data stored in a custom dimension of a custom telemetry event emitted to application insights, and getting some weird behavior. It seems like the JSON can't be parsed normally, but if I pass it through strcat it is able to parse the json just fine.
customEvents
| where name == "PbConfigFilterComponentSaved"
| take 1
| project
jsonType=gettype(customDimensions.Json),
parsedType=gettype(parse_json(customDimensions.Json)),
strcatType=gettype(strcat('', customDimensions.Json)),
strcatParsedType=gettype(parse_json(strcat('', customDimensions.Json)))
Result:
jsonType: string
parsedType: string
strcatType: string
strcatParsedType: dictionary
Is there a better approach to getting parse_json to work on this kind of value?
Update
In case it's in any way relevant, here's the value of customDimensions.Json:
{"filterComponentKey":"CatalystAgeRange","typeKey":"TemporalConstraint","uiConfig":{"name":"Age","displayMode":"Age"},"config":{"dateSelector":"pat.BirthDTS"},"disabledForScenes":false,"disabledForFilters":false}
Could you please demonstrate a sample record that isn't parsed correctly?
Speculating (before seeing the data): Have you verified the final paragraph here doesn't apply to your case?
It is somewhat common to have a JSON string describing a property bag in which one of the "slots" is another JSON string. […] In such cases, it is not only necessary to invoke parse_json twice, but also to make sure that in the second call, tostring will be used. Otherwise, the second call to parse_json will simply pass-on the input to the output as-is, because its declared type is dynamic.
The type of customDimensions is dynamic and so accessing a property like customDimensions.json from it will return a string typed as dynamic.
You have to explicitly cast it as string and then parse it:
todynamic(tostring(customDimensions.json)).property
I think the "Notes" section in the documentation is exactly the issue, as mentioned by Yoni L. in the previous answer.

Request versus Request.QueryString

What is the difference between these two in VBScript:
Request("startDate")
Request.QueryString["startDate"]
And where is Request("startDate") documented? I don't see this usage here:
http://www.w3schools.com/asp/asp_ref_request.asp
The official documentation for the Request object in ASP classic is here: http://msdn.microsoft.com/en-us/library/ms524948%28VS.90%29.aspx
Quoting the relevant part for this question:
All variables can be accessed directly by calling Request(variable)
without the collection name. In this case, the Web server searches the
collections in the following order:
QueryString
Form
Cookies
ClientCertificate
ServerVariables
If a variable with the same name exists in more than one collection,
the Request object returns the first instance that the object
encounters.
EDIT: AnthonyWJones made a great comment on the question: Avoid using the Request("name") syntax. In fact, this is mentioned in the documentation link above:
It is strongly recommended that when referring to members of a
collection the full name be used. For example, rather than
Request.("AUTH_USER") use Request.ServerVariables("AUTH_USER"). This
allows the server to locate the item more quickly.
See Request() vs Request.QueryString()
From what I understand when you use Request on it's own it will return the first matched item in the request collection. well explained in the attached solution.
Sorry to dredge up this question, but given the warnings against using Request("param"), I had to add my two cents. In this particular case there's a good reason to use Request("param") instead of Request.QueryString("param"): It allows you to write code that will accept parameters as part of a query string or when submitted through a form. I regularly run into situations where that is not only handy, but desirable.

Set HttpContext.Current.Request.Browser.Type in ASP.NET

Is there a way to set HttpContext.Current.Request.Browser.Type in ASP.NET. That is a read-only, string property. So you cannot really just assign a string to it. Tried initializing Browser property which is of type HttpBrowserCapabilities, but it has only one constructor and does not take any parameters and browser Type is still null. The reason why I want to be able to set Type for browser is that my unit test is failing as Type property is null.
Edit per null check comments:
I could definitely modify code to check for null, but that will be just for my unit test as when the requests come from browsers, that value is never null. Hence not quite excited about doing that. But it can be my last resort.
You can define your own browser definition files which ASP.net will then use. Check out http://forums.asp.net/p/955969/1176101.aspx.
So if you know what browser it's failing on you could setup a browser file for it. However, I agree that checking for null values makes more sense as it accounts for a lot more possiblities that way.
You might want to think about refactoring your code to use HttpContextBase instead of relying directly on the concrete type.
By doing so you could simply create a stub object that provides the behavior you want. Eventually implementing your own HttpBrowserCapabilitiesBase object.
You would then have full control to use your mock types during unit testing. Indeed that is what they were created for.

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.

What is the significance of the Type parameter in the RegisterClientScriptBlock method call?

This is an example of RegisterClientScriptBlock
Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "key","scriptblock", True)
Why do the method needs the type as the first parameter ?
Thanks.
From the MSDN docs: "A client script is uniquely identified by its key and its type. Scripts with the same key and type are considered duplicates."
Basically it gives you an additional way to uniquely identify your scripts. You could have the same key value across different types of controls.
I've wondered about this myself. As far as I can see in Reflector, it's not used by RegisterClientScriptBlock() directly, it is only passed through to be used by the GetHashCode() method of the ScriptKey class. There it probably serves to uniquely identify the script block further beyond just the user-supplied key, since it is linked to the specified type.
There a post on why this could lead to trouble, but I've never actually encountered this. It comes down to this: when you inherit from a control that has this piece of code, the GetType will return something else. This way, the key will differ and the script will be added a second time if you have both controls on your page. This could potentially lead to javascript problems.
The solution would be to not use GetType but typeof() instead. In VB.Net:
Page.ClientScript.RegisterClientScriptBlock(GetType(MyClass), "key","scriptblock", True)
But again, this is an exceptional case.

Resources