Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Trim quotes from template #5838

Merged
merged 1 commit into from
Mar 3, 2017
Merged

Trim quotes from template #5838

merged 1 commit into from
Mar 3, 2017

Conversation

ryanbrandenburg
Copy link
Contributor

Fixes #5835. Will add functional tests after #5837 is merged.

@ryanbrandenburg
Copy link
Contributor Author

We shouldn't be enforcing the presense of quotes at this level, just removing them right?

@@ -22,7 +22,7 @@ public static bool TryGetRouteTemplate(RazorProjectItem projectItem, out string
if (content.StartsWith(PageDirective, StringComparison.Ordinal))
{
var newLineIndex = content.IndexOf(Environment.NewLine, PageDirective.Length);
template = content.Substring(PageDirective.Length, newLineIndex - PageDirective.Length).Trim();
template = content.Substring(PageDirective.Length, newLineIndex - PageDirective.Length).Trim().Trim('"');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if there's no newline?

@rynowak
Copy link
Member

rynowak commented Feb 22, 2017

Please add unit tests as well as updating the functional tests, my PR has been merged.

@ryanbrandenburg
Copy link
Contributor Author

🆙📅

Assert.Equal("Some/Path/{value}", template);
}

[Fact(Skip = "Re-evaluate this scenario after we use Razor to parse this stuff")]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding was that we're not going to worry about this scenario for now, correct me if that's wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah let's ignore this for now

@@ -11,18 +11,43 @@ public static class PageDirectiveFeature
{
public static bool TryGetRouteTemplate(RazorProjectItem projectItem, out string template)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this function is kind of serving double duty to determing if it's a RazorPage (the bool return value) and extract the template (the out value). If that was intentional why, and if not might it be clearer with two functions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is really more like TryGetPageDirective

const string PageDirective = "@page";

var stream = projectItem.Read();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we have a guarantee that the underlying stream for projectItem.Read can be read twice?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't through, it's read once here and then closed at line 32

if (stream == null)
{
throw new ArgumentOutOfRangeException($"{nameof(projectItem)}.{nameof(projectItem.Read)} can't return null.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kinda a strange check to put in

}

if (content.StartsWith(PageDirective, StringComparison.Ordinal))
{
var newLineIndex = content.IndexOf(Environment.NewLine, PageDirective.Length);
template = content.Substring(PageDirective.Length, newLineIndex - PageDirective.Length).Trim();
var endOfDirective = content.IndexOf(Environment.NewLine, PageDirective.Length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to support all possible newlines on all possible systems. I would suggest creating a SourceDocument here and then using SourceDocument.Lines. We want to have explicit newline handling in as few places as possible.

The rest of the thing");

// Act & Assert
Assert.True(PageDirectiveFeature.TryGetRouteTemplate(projectItem, out template));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out var template 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good cleanup item once we're on C#7.

}

[Fact]
public void TryGetRouteTemplate_NoQuotesAroundPath()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave a comment here that in the future this will not be supported

@@ -0,0 +1,6 @@
@*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eww get rid of

var endOfDirective = content.IndexOf(Environment.NewLine, PageDirective.Length);
if (endOfDirective < 0)
{
var otherNewLine = Environment.NewLine == "/r/n" ? "/n" : "/r/n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ain't no slash gonna be a backslash if you ain't gonna slash the slash 🔫🔫 & 🌹🌹 .

endOfDirective = content.Length;
}

template = content.Substring(PageDirective.Length, endOfDirective - PageDirective.Length).Trim().Trim('"');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will trim an arbitrary number of double-quotes from the start and end of the string. That is, the string """"""""hi, mom""""""""""""""""""" will become hi, mom. Is that intended here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hint: I strongly hope that this is not the intention - having too many quotes like this really ought to be an error.

@ryanbrandenburg
Copy link
Contributor Author

🆙📅

}
else
{
template = template.Substring(1, template.Length - 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point is it guaranteed that there is a start quote and end quote?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I de-negafied the code the make this more clear.

Assert.True(PageDirectiveFeature.TryGetPageDirective(projectItem, out template));
Assert.Equal("Some/Path/{value}", template);
}
[Fact]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\r\n

public void TryGetPageDirective_WrongNewLine()
{
// Arrange
string wrongNewLine = "\r\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And can just use a ternary expression here?


namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{
public class PageDirectiveFeatureTest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the quote trimming has changed, should there be a test to make sure that extraneous quotes are invalid? Or at least to see what happens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's my understanding that @rynowak wasn't wanting to mess with parsing and verifying these too much since we're eventually going to transition to using razor parsing which would deal with a lot of this for us. As written if you have multiple quotes it will include the extras as part of the template and I've added a test which proves that. I think this boils down to how much verifying of the template we want to do in this function. What if we have "this/is/"a/template" or "this/is/'a/template", both of these are invalid url parts, but is it this functions job to ensure that out template is a valid part of a url?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that'd be good to discuss with @rynowak

Copy link
Member

@Eilon Eilon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm signing off on the part I reviewed about quote trimming.

{
var newLineIndex = content.IndexOf(Environment.NewLine, PageDirective.Length);
template = content.Substring(PageDirective.Length, newLineIndex - PageDirective.Length).Trim();
template = content.Substring(PageDirective.Length, content.Length - PageDirective.Length).Trim();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to trim again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This second trim will execute after the Substring which removes "@page" and will trim off any spaces between @page and the first ". Should I make it TrimStart to make that more explicit?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Ya TrimSTart would help.

}

if (content.StartsWith(PageDirective, StringComparison.Ordinal))
if (content != null && content.StartsWith(PageDirective, StringComparison.Ordinal))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easier to read if you just do:

if (content == null || !content.StartsWith(PageDirective, StringComparison.Ordinal))
{
    return false;
}

and then un-nest the rest.

// If it's not in quotes it's not our template
else
{
template = string.Empty;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting case. If a user writes: @page foo in bar.cshtml we'll map the Razor page to /bar. However, the user will then try to access their Razor page at /bar/foo with no luck (it'll 404). Ideally we could raise @page errors on startup so they could be fixed without a user wondering why they can't hit their page.

Not much we can do in this PR so mostly just throwing this out to thinking about it. What's everyone's thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that silently ignoring this is going to cause confusion. We could probably log this.

@ryanbrandenburg
Copy link
Contributor Author

🆙📅

Copy link
Contributor

@NTaylorMullen NTaylorMullen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just wanted to raise awareness for everyone else on #5838 (comment)

Copy link
Contributor

@ajaybhargavb ajaybhargavb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one minor comment

{
content = streamReader.ReadLine();
} while (content != null && string.IsNullOrWhiteSpace(content));
content = content != null ? content.Trim() : content;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

content = content?.Trim()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also bring this outside Using block

@ryanbrandenburg
Copy link
Contributor Author

I filed #5868 for that comment @NTaylorMullen.

@ryanbrandenburg ryanbrandenburg force-pushed the RazorPagesTrimQuotes branch 2 times, most recently from e8c41b6 to 45d3f5f Compare March 3, 2017 01:07
@ryanbrandenburg ryanbrandenburg merged commit 85e28ae into dev Mar 3, 2017
@ryanbrandenburg ryanbrandenburg deleted the RazorPagesTrimQuotes branch March 3, 2017 17:52
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants