How to escape odata uri segment starting dollar sign ($) - c#

Running this query:
"https://someurl.com/graph/users/%24myuser%40myorg.org/licenseDetails?$select=skuId,skuPartNumber"
Results in:
"The request URI is not valid. Since the segment 'users' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource"
After some playing around, I managed to make it work by adding a second dollarsign (%24) before myuser.
This seems to be poorly documented, even here https://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/abnf/odata-abnf-construction-rules.txt.
Is there a c# library that correctly escapes a given literal string for odata instead of everyone manually hitting problems from time to time ?
Shouldn't the doc be improved for these special cases that don't seem to be documented ?

A $ prefix in an OData url typically designates that your are about to use a System Query Option, such as $filter, $select or $expand. This is likely causing your key to be interpreted as such.
Since you're using an entity key to access a specific entity then navigate to one of it's navigation properties, you can typically provide the key directly within parenthesis on the entity. This is simple when you don't have a composite key, and looks like this:
/users('my-key-value')
You can then expand a particular navigation property and select down to specific properties (assuming the implementation is compliant with this) in the same way you were previously attempting, leading to
/users('$myuser#myorg.org')/licenseDetails?$select=skuId,skuPartNumber

As stated by Jonathon Chase, you can use /users('$myuser#myorg.org')/licenseDetails as an alternative syntax.

Related

.NET Web API Slash in Route

I have a .NET Web API v2 and need to define a route that can contain forward slashes at any point in the route. I have it configured (something) like this in WebApiConfig:
config.Routes.MapHttpRoute(
name: "SomeRouteName",
routeTemplate: "api/summary/{*token}",
defaults: new { controller = "Summary" });
Unfortunately the token contains slashes and there's nothing I can do about it at this point. The above route works in most cases if the slash is not at the beginning of the token. So that takes care of most cases. But if token begins with slash(es), it doesn't work because that first slash gets interpreted as part of the URL I assume and gets eaten. So in my controller action, I have the following code (admittedly a hack that I'm trying to avoid):
if (summary == null)
{
summary = _repo.GetSummary($"/{token}");
}
Obviously, this will only work for a single slash. I could do a loop and add more, but there isn't way to know how many it could be. Currently no tokens in my DB begin with two slashes, so this bad code works for now. It was implemented as a band-aid until a better solution is found.
Edit: This references the * route, which mostly fixed my original issue, but still doesn't match the first slashes: URLs with slash in parameter?
Since OP said in some comment:
There is no purpose -- but the tokens are generated and not
necessarily by my code. So I don't have control over the token
generation.
and also:
I've attempted to UrlEncode /Decode to see if this works, but the
slash (encoded as %2F) still gets eaten for whatever reason. As a side
note, I can say that Base64 encoding it will fix this but that I can't
change this at this point because it would break the API for existing
apps.
I would say that one of best choices to avoid issues with special characters is firstly encoding the whole token as a base 64 string, and then url-encode it to encode possible characters like =.
That is, you can configure a route where you don't need {token*} but just {token}. If you need to simplify the token decoding, you can implement an ActionFilterAttribute that decodes the so-called bound parameter under the hoods.
Others have already done this way...
OAuth2 already sends basic authentication's credentials encoding them as a base64 string (you convert user:password to the whole base 64 string).
It's a common way of avoding these issues and base 64 strings can be decoded in every modern client and server platform.

What is the use of uriAddress.GetLeftPart and how to use it in C#?

What is the use of uriAddress.GetLeftPart and how do i use it in C#. Please provide one example. If i need to extract
http://localhost:2008/
part from
http://localhost:2008/ClientDashBoard/CreateDocument
Can i use uriAddress.GetLeftPart for doing that job?
Yes.
In general, if you have any question about a .NET class library method, I recommend having a look at the MSDN documentation as the first step. You can easily access it in Visual Studio by putting the cursor on the method in question and hitting F1. For example, the MSDN page on Uri.GetLeftPart has all the information you need:
The GetLeftPart method returns a string containing the leftmost portion of the URI string, ending with the portion specified by part.
[...]
The following examples show a URI and the results of calling GetLeftPart with Scheme, Authority, Path, or Query.
URI Scheme Authority [...]
http://www.contoso.com/index.htm?date=today http:// http://www.contoso.com
So, apparently, myUri.GetLeftPart(UriPartial.Authority) is (almost) exactly what you need.
Do note the following, though:
GetLeftPart includes delimiters in the following cases:
[...]
Authority does not include the path delimiter.
So you will get http://localhost:2008 instead of http://localhost:2008/. Fixing that is left as an exercise to the reader...

Regexp: finding multiple matches for a single asterisked group

Suppose we have /(a*b)*/ regexp, and we would like to get
{"aab", "ab", "aaab"}
as a set of matches for the only pair of parenthesis (group) when matching with "aababaaab" string. Sure we could modify this regexp with g modifier, and run it in a loop, but there're a lot of more complicated examples, when such rewrite is unsuitable due to code blowup. .NET has such an interface called a capture.
Is there any way to do the same in JS either using standard library or external libraries?
I don't know if I understood correctly, but if you want to get the minimun expressión of your query you can use a ungreedy match:
'aababaaab'.match(/(a*b)+?/g);
The problem of this is that you will not get all the combinations, but you seem not care about that in your question.

Regular Expression to validate a URL or domain name.

Can someone please let me know what is wrong with my regular expression? I’m trying to just validate the beginning to URLs, mainly just host names (i.e. www.yahoo.com).
Regular Expression: ^(((ht|f)tp(s?))\:\/\/)?(www.)?([a-zA-Z0-9\-\.]{1,63})+\.([a-zA-Z]{2,5})$
Testing Values:
test.com – passes
test.c2om – fails
test.test.com – passes
test.test.c2om – fails
test.test.test.com – passes
test.test.test.c2om – INVALID REGEX PATTERN
This should return false, but instead returns nothing, both using javascript and c#… If you remove the {1,63} restriction on the size of the subdomain, it works…
You've created a catastrophic pattern - The engine will try to match ([a-zA-Z0-9\-\.]{1,63})+ in many ways until it fails. A simple solution is to remove {1,63}, as you've noted, it doesn't seem to be adding anything anyway.
Another option is to use the dots as anchors, so you cannot backtrack between them (this only gives you one way to match the text, and assumably, what you're trying to do):
([a-zA-Z0-9\-]{1,63}\.)*[a-zA-Z0-9\-]{1,63}
Keep in mind that isnt very correct anymore to assume all-ASCII-English letters in domain names. For example http://אתר.קום is a legal (and working) url.

validating user input tags

I know this question might sound a little cheesy but this is the first time I am implementing a "tagging" feature to one of my project sites and I want to make sure I do everything right.
Right now, I am using the very same tagging system as in SO.. space seperated, dash(-) combined multiple words. so when I am validating a user-input tag field I am checking for
Empty string (cannot be empty)
Make sure the string doesnt contain particular letters (suggestions are welcommed here..)
At least one word
if there is a space (there are more than one words) split the string
for each splitted, insert into db
I am missing something here? or is this roughly ok?
Split the string at " ", iterate over the parts, make sure that they comply with your expectations. If they do, put them into the DB.
For example, you can use this regex to check the individual parts:
^[-\w]{2,25}$
This would limit allowed input to consecutive strings of alphanumerics (and "_", which is part of "\w" as well as "-" because you asked for it) 2..25 characters long. This essentially removes any code injection threat you might be facing.
EDIT: In place of the "\w", you are free to take any more closely defined range of characters, I chose it for simplicity only.
I've never implemented a tagging system, but am likely to do so soon for a project I'm working on. I'm primarily a database guy and it occurs to me that for performance reasons it may be best to relate your tagged entities with the tag keywords via a resolution table. So, for instance, with example tables such as:
TechQuestion
TechQuestionID (pk)
SubjectLine
QuestionBody
TechQuestionTag
TechQuestionID (pk)
TagID (pk)
Active (indexed)
Tag
TagID (pk)
TagText (indexed)
... you'd only add new Tag table entries when never-before-used tags were used. You'd re-associate previously provided tags via the TechQuestionTag table entry. And your query to pull TechQuestions related to a given tag would look like:
SELECT
q.TechQuestionID,
q.SubjectLine,
q.QuestionBody
FROM
Tag t INNER JOIN TechQuestionTag qt
ON t.TagID = qt.TagID AND qt.Active = 1
INNER JOIN TechQuestion q
ON qt.TechQuestionID = q.TechQuestionID
WHERE
t.TagText = #tagText
... or what have you. I don't know, perhaps this was obvious to everyone already, but I thought I'd put it out there... because I don't believe the alternative (redundant, indexed, text-tag entries) wouldn't query as efficiently.
Be sure your algorithm can handle leading/trailing/extra spaces with no trouble = )
Also worth thinking about might be a tag blacklist for inappropriate tags (profanity for example).
I hope you're doing the usual protection against injection attacks - maybe that's included under #2.
At the very least, you're going to want to escape quote characters and make embedded HTML harmless - in PHP, functions like addslashes and htmlentities can help you with that. Given that it's for a tagging system, my guess is you'll only want to allow alphanumeric characters. I'm not sure what the best way to accomplish that is, maybe using regular expressions.

Categories