Skip to content
This repository has been archived by the owner on Oct 18, 2018. It is now read-only.

A particularly nasty bug that I fixed myself! (all the while learning about GitHub) #7

Closed
wants to merge 60 commits into from
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
462934a
#6 - Change "Title" attribute to "title" to avoid invalid XHTML
Jan 30, 2012
3bbbde5
#8 - Sort post categories in ascending order by default
jeremy-jameson Jan 31, 2012
8e6d7d7
#9 - Comment out CSS rule that refers to obsolete file (/Subtext.Web/…
jeremy-jameson Jan 31, 2012
740a542
#10 - Fix bug when a tag is specified using a relative URL instead of…
jeremy-jameson Jan 31, 2012
8a7b893
#10 - Allow tags on blog posts to refer to Subtext blog (rather than,…
jeremy-jameson Jan 31, 2012
7ca161d
#11 - Expose the "Entry" entity object in the ViewPost control (so th…
jeremy-jameson Jan 31, 2012
f9215e2
#12 - Fix bug where "Submit" button would show "undefined" after part…
jeremy-jameson Jan 31, 2012
5a8af0a
#14 - Avoid SecurityException when category is not found and Subtext …
jeremy-jameson Jan 31, 2012
ac90a41
#15 - Avoid error when post is not found and skin control contains co…
jeremy-jameson Jan 31, 2012
a34b8ff
#16 - Allow errors in Lucene.Net.QueryParsers.QueryParser to be avoid…
jeremy-jameson Jan 31, 2012
e8e4df8
#17 - Allow server-relative paths to be specified for CSS files in sk…
jeremy-jameson Jan 31, 2012
f59d7c3
#18 - jQuery references need to specify "https://" (not "http://") wh…
jeremy-jameson Jan 31, 2012
24fb641
#19 - Category links do not specify correct URLs when browsing Subtex…
jeremy-jameson Jan 31, 2012
300650f
#20 - Fix numerous issues with pingback functionality in Subtext:
jeremy-jameson Jan 31, 2012
59f0b88
#8 - Explicitly specify "ascending" sort order (per Phil's request)
jeremy-jameson Feb 2, 2012
c72b934
#18 - Refine method for specifying "http://" or "https://" for jQuery…
jeremy-jameson Feb 2, 2012
5c6c81d
Merge changes from upstream (https://github.com/haacked/Subtext)
jeremy-jameson Nov 13, 2019
b7af44f
Upgrade log4net to version 1.2.11
jeremy-jameson Nov 13, 2019
8dabe2f
Upgrade solution to Visual Studio 2015
jeremy-jameson Nov 13, 2019
3b2702b
Add blog skin and related files for Technology Toolbox website
jeremy-jameson Nov 13, 2019
f806b83
Tweak messages displayed to blog readers
jeremy-jameson Nov 13, 2019
07461c7
Expose EntryViewModel (instead of Entry) in ViewPost control (to be c…
jeremy-jameson Nov 13, 2019
0b55d16
Fix merge bug
jeremy-jameson Nov 14, 2019
969f2c5
Remove blog skin and related files for Technology Toolbox website
jeremy-jameson Nov 14, 2019
a0dc419
Add ASP.NET MVC project type GUIDs to SubText.Web.csproj
jeremy-jameson Nov 14, 2019
d018e59
Add .vs/ and App_Data/ to .gitignore
jeremy-jameson Nov 14, 2019
9bb3ec6
Upgrade assemblies for SQL Server Management Objects (SMO)
jeremy-jameson Nov 14, 2019
bf7968d
Fix bug in unit tests due to time zone differences
jeremy-jameson Nov 16, 2019
f25d28e
Avoid ArgumentOutOfRangeException when browsing to ".../blog"
jeremy-jameson Nov 16, 2019
9eacf71
Fix another bug when attempting to redirect from "/blog" to "/blog/jj…
jeremy-jameson Nov 16, 2019
a338dd6
Support "placeholder" Gravatar image in blog skins
jeremy-jameson Nov 16, 2019
6277fd4
Fix HTTP 404 when browsing to ".../blog/jjameson/tags"
jeremy-jameson Nov 16, 2019
b4410ba
jQuery references need to specify "https://" (not "http://") when bro…
jeremy-jameson Nov 16, 2019
607604d
Change web project to use IIS Express
jeremy-jameson Nov 17, 2019
b761a46
Support alternate URLs without changing the original hostname
jeremy-jameson Nov 18, 2019
8445963
Upgrade test project to .NET Framework 4.5
jeremy-jameson Nov 20, 2019
3fc6ce7
Reinstall NuGet packages
jeremy-jameson Nov 20, 2019
0c03a66
Install MSTest NuGet packages
jeremy-jameson Nov 20, 2019
e385d47
Convert simplest unit test from MbUnit to MSTest
jeremy-jameson Nov 20, 2019
6b6272d
Convert tests from MbUnit to MSTest (first pass)
jeremy-jameson Nov 20, 2019
2920cd3
Convert database integration tests from MbUnit to MSTest
jeremy-jameson Nov 20, 2019
2d7b63d
Convert "multiple culture" tests from MbUnit to MSTest
jeremy-jameson Nov 20, 2019
9f23573
Convert "TypeFixture" test from MbUnit to MSTest
jeremy-jameson Nov 20, 2019
b59d5a1
Remove MbUnit references from UnitTests.Subtext project
jeremy-jameson Nov 20, 2019
900aed0
Use SQL Server Express LocalDB for running tests
jeremy-jameson Nov 21, 2019
24b3b57
Remove hack added to get test to pass in Visual Studio 2019
jeremy-jameson Nov 21, 2019
2865680
Add Microsoft.SqlServer.SqlClrProvider.dll
jeremy-jameson Nov 21, 2019
1b92c93
Merge pull request #7 from technology-toolbox/users/jjameson/dev
jeremy-jameson Nov 21, 2019
5393023
Refine messages for test assertions
jeremy-jameson Nov 21, 2019
8235d6b
Verify entries before verifying order of results
jeremy-jameson Nov 21, 2019
111add7
Explicitly set the "date published" property on entries
jeremy-jameson Nov 21, 2019
9b624f3
Merge pull request #9 from technology-toolbox/users/jjameson/dev
jeremy-jameson Nov 21, 2019
2305608
Fix category URLs in sitemap
jeremy-jameson Nov 22, 2019
4da8a94
Fix archive URLs in sitemap
jeremy-jameson Nov 22, 2019
cd2b7b9
Merge pull request #12 from technology-toolbox/users/jjameson/dev
jeremy-jameson Nov 22, 2019
a0847a8
Bump DotNetZip from 1.9.1.8 to 1.11.0 in /src/SubtextUpgrader
dependabot[bot] Mar 25, 2021
01bd7f3
Bump log4net from 1.2.11 to 2.0.10 in /src/Subtext.Web
dependabot[bot] Apr 13, 2021
01ffe1f
Bump log4net from 1.2.11 to 2.0.10 in /src/Subtext.Framework
dependabot[bot] Apr 13, 2021
6a516b4
Bump log4net from 1.2.11 to 2.0.10 in /src/UnitTests.Subtext
dependabot[bot] Apr 13, 2021
029222b
Bump DotNetZip from 1.9.1.8 to 1.11.0 in /src/Subtext.Web
dependabot[bot] Mar 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -1126,6 +1126,8 @@ WHERE (c.CategoryID = @CategoryID OR @CategoryID IS NULL)
AND (c.CategoryType = @CategoryType OR @CategoryType IS NULL)
AND (c.BlogId = @BlogId OR @BlogId IS NULL)
AND c.Active <> CASE @IsActive WHEN 0 THEN -1 else 0 END
ORDER BY
c.Title
Copy link
Owner

Choose a reason for hiding this comment

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

Let's be explicit about ordering. This should probably be:

ORDER BY
    c.Title ASC

Copy link
Author

Choose a reason for hiding this comment

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

Done



GO
Expand Down
Expand Up @@ -233,9 +233,22 @@ public static Uri ToFullyQualifiedUrl(this VirtualPath virtualPath, Blog blog, s
}

var builder = new UriBuilder { Scheme = scheme, Host = blog.Host };
if (HttpContext.Current != null && HttpContext.Current.Request != null && HttpContext.Current.Request.Url.Port != 80)
if (HttpContext.Current != null
&& HttpContext.Current.Request != null)
{
builder.Port = HttpContext.Current.Request.Url.Port;
if (HttpContext.Current.Request.IsSecureConnection == true)
{
builder.Scheme = "https";
Copy link
Owner

Choose a reason for hiding this comment

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

Nice catch! Do we have unit tests for this method anywhere? I didn't see any updated tests.

Copy link
Author

Choose a reason for hiding this comment

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

No...while I managed to get the unit tests working in the 2.5 solution (i.e. Visual Studio 2008 and MbUnit), I haven't had any success thus far with the current 2.6 solution. MbUnit just barfs on me (complaining about the version of the .NET Framework being used).

Note that I'm a Visual Studio "Team Suite" kind of guy, so I know next to nothing about MbUnit. I'd love to get it working -- and subsequently write tests first when making changes or enhancements -- but I'm going to need a little help to make that happen.

Regardless of my current blocking issue with MbUnit, for this particular fix would it even be possible to write a unit test, given the call to HttpContext.Current? Sorry if this seems ignorant, but in my past experience I've always passed in an HttpContextBase parameter to methods when doing TDD.

Copy link
Owner

Choose a reason for hiding this comment

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

Ok, don't worry about it for now. :) Yeah, this would be hard to test as it stands. But that method would get annoying if we had to pass in an HttpContextBase parameter too. Though that's probably the right thing to do. :) I'll assume you tested this thoroughly.


if (HttpContext.Current.Request.Url.Port != 443)
{
builder.Port = HttpContext.Current.Request.Url.Port;
}
}
else if (HttpContext.Current.Request.Url.Port != 80)
{
builder.Port = HttpContext.Current.Request.Url.Port;
}
}
return new Uri(builder.Uri, virtualPath);
}
Expand Down
12 changes: 12 additions & 0 deletions src/Subtext.Framework/Text/HtmlHelper.cs
Expand Up @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
Expand Down Expand Up @@ -824,6 +825,17 @@ public static IList<string> ParseTags(this string html)
Uri url;
if (Uri.TryCreate(urlStr, UriKind.RelativeOrAbsolute, out url))
{
if (url.IsAbsoluteUri == false)
{
// HACK: You can't access Segments property on
// relative Uri
url = new Uri(
new Uri("http://foobar"),
urlStr);
}

Debug.Assert(url.IsAbsoluteUri == true);

string[] seg = url.Segments;
string tag = HttpUtility.UrlDecode(seg[seg.Length - 1].Replace("/", ""));

Expand Down
6 changes: 5 additions & 1 deletion src/Subtext.Framework/Tracking/Notification.cs
Expand Up @@ -35,6 +35,7 @@

#endregion

using System;
using Subtext.Framework.Components;
using Subtext.Framework.Configuration;
using Subtext.Framework.Routing;
Expand Down Expand Up @@ -64,9 +65,12 @@ public static void Run(Entry entry, Blog blog, BlogUrlHelper urlHelper)

if (entry != null)
{
VirtualPath blogUrl = urlHelper.BlogUrl();
Uri fullyQualifiedUrl = blogUrl.ToFullyQualifiedUrl(blog);

var notify = new Notifier
{
FullyQualifiedUrl = urlHelper.BlogUrl(),
FullyQualifiedUrl = fullyQualifiedUrl.AbsoluteUri,
BlogName = blog.Title,
Title = entry.Title,
PostUrl = urlHelper.EntryUrl(entry).ToFullyQualifiedUrl(blog),
Expand Down
Expand Up @@ -72,7 +72,7 @@ public class TrackBackNotificationProxy
return SendPing(trackBackUrl, parameters);
}
}
return true;
return false;
Copy link
Owner

Choose a reason for hiding this comment

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

Ummm, whoops! Heh. Nice catch.

}

private static bool SendPing(Uri trackBackItem, string parameters)
Expand Down
12 changes: 8 additions & 4 deletions src/Subtext.Framework/Tracking/TrackHelpers.cs
Expand Up @@ -48,12 +48,16 @@ namespace Subtext.Framework.Tracking
/// </summary>
public static class TrackHelpers
{
//Text to insert into a file with pinkback service location
public static string GetPingPackTag(BlogUrlHelper urlHelper)
//Text to insert into a file with pingback service location
public static string GetPingbackTag(BlogUrlHelper urlHelper, Entry entry)
{
VirtualPath blogUrl = urlHelper.BlogUrl();
Uri absoluteUrl = blogUrl.ToFullyQualifiedUrl(entry.Blog);

return string.Format(CultureInfo.InvariantCulture,
"<link rel=\"pingback\" href=\"{0}Services/Pingback.aspx\"></link>",
urlHelper.BlogUrl());
"<link rel=\"pingback\" href=\"{0}Services/Pingback/{1}.aspx\"></link>",
absoluteUrl.AbsoluteUri,
entry.Id);
}

//Body of text to insert into a post with Trackback
Expand Down
Expand Up @@ -126,9 +126,14 @@ public static string GetStylesheetHrefPath(string skinPath, Style style)
{
return HttpHelper.ExpandTildePath(style.Href);
}
return style.Href.StartsWith("/") || style.Href.StartsWith("http://") || style.Href.StartsWith("https://")
? style.Href
: skinPath + style.Href;
else if (IsStyleRemote(style) == true)
{
return style.Href;
}
else
{
return skinPath + style.Href;
}
}

/// <summary>
Expand Down Expand Up @@ -358,8 +363,9 @@ public static bool CanStyleBeMerged(Style style)

private static bool IsStyleRemote(Style style)
{
if (style.Href.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
style.Href.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
if (style.Href.StartsWith("/")
|| style.Href.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
|| style.Href.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/Subtext.Web/Routes.cs
Expand Up @@ -125,6 +125,7 @@ public static void RegisterRoutes(SubtextRouteMapper routes)


routes.MapControls("tag", "tags/{tag}/default.aspx", null, new[] { "TagEntryList" });
routes.MapControls("tag-default", "tags/{tag}", null, new[] { "TagEntryList" });
routes.MapControls("tag-cloud", "tags/default.aspx", null, new[] { "FullTagCloud" });
routes.MapHttpHandler<RssTagHandler>("tag-rss", "tags/{tag}/rss.aspx");

Expand Down
4 changes: 3 additions & 1 deletion src/Subtext.Web/Scripts/common.js
Expand Up @@ -41,7 +41,9 @@ function endRequest(sender, args)
if (button)
{
button.disabled = false;
button.value = button.oldValue;
if (button.oldValue && button.oldValue != '') {
button.value = button.oldValue;
}
if (button.className == 'button-disabled')
{
button.className = 'buttonSubmit';
Expand Down
15 changes: 13 additions & 2 deletions src/Subtext.Web/UI/Controls/StoryList.cs
Expand Up @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using Subtext.Framework;
using Subtext.Framework.Components;
using Subtext.Framework.Data;
Expand Down Expand Up @@ -54,8 +55,18 @@ protected override void OnLoad(EventArgs e)

if (lc == null)
{
HttpHelper.SetFileNotFoundResponse();
return;
// When running under Medium trust, calling HttpHelper.SetFileNotFoundResponse() causes an exception
// while attempting to read the system.web/customErrors section of the Web.config file
// ("System.Security.SecurityException: Request for the permission of type
// 'System.Configuration.ConfigurationPermission, System.Configuration, Version=2.0.0.0, Culture=neutral,
// PublicKeyToken=b03f5f7f11d50a3a' failed.").
//
// Therefore, just throw 404 HttpException instead.
//
//HttpHelper.SetFileNotFoundResponse();
//return;

throw new HttpException(404, "Category not found.");
}

ICollection<Entry> ec = Cacher.GetEntriesByCategory(count, lc.Id, SubtextContext);
Expand Down
66 changes: 40 additions & 26 deletions src/Subtext.Web/UI/Controls/ViewPost.cs
Expand Up @@ -17,6 +17,7 @@

using System;
using System.Globalization;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using System.Web.UI.WebControls;
Expand All @@ -40,6 +41,8 @@ public partial class ViewPost : BaseControl
const string LinkToComments = "<a href=\"{0}#feedback\" title=\"View and Add Comments\">{1}{2}</a>";
const string LinkToEnclosure = "<a href=\"{0}\" title = \"{1}\">{2}</a>{3}";

protected Entry Entry { get; private set; }

/// <summary>
/// Loads the entry specified by the URL. If the user is an
/// admin and the skin supports it, will also display an edit
Expand All @@ -52,81 +55,81 @@ protected override void OnLoad(EventArgs e)
base.OnLoad(e);

//Get the entry
Entry entry = Cacher.GetEntryFromRequest(true, SubtextContext);
Entry = Cacher.GetEntryFromRequest(true, SubtextContext);

//if found
if (entry != null)
if (Entry != null)
{
BindCurrentEntryControls(entry, this);
BindCurrentEntryControls(Entry, this);

DisplayEditLink(entry);
DisplayEditLink(Entry);

var statistics = DependencyResolver.Current.GetService<IStatisticsService>();
statistics.RecordWebView(new EntryView { EntryId = entry.Id, BlogId = Blog.Id });
statistics.RecordWebView(new EntryView { EntryId = Entry.Id, BlogId = Blog.Id });

//Set the page title
Globals.SetTitle(entry.Title, Context);
Globals.SetTitle(Entry.Title, Context);

//Sent entry properties
TitleUrl.Text = entry.Title;
TitleUrl.Text = Entry.Title;
ControlHelper.SetTitleIfNone(TitleUrl, "Title of this entry.");
TitleUrl.NavigateUrl = Url.EntryUrl(entry);
Body.Text = entry.Body;
TitleUrl.NavigateUrl = Url.EntryUrl(Entry);
Body.Text = Entry.Body;
if (PostDescription != null)
{
PostDescription.Text = string.Format(CultureInfo.InvariantCulture, "{0} {1}",
entry.DateSyndicated.ToLongDateString(),
entry.DateSyndicated.ToShortTimeString());
Entry.DateSyndicated.ToLongDateString(),
Entry.DateSyndicated.ToShortTimeString());
}
Trace.Write("loading categories");
if (Categories != null)
{
Categories.LinkCategories = Repository.GetLinkCategoriesByPostId(entry.Id);
Categories.LinkCategories = Repository.GetLinkCategoriesByPostId(Entry.Id);
Categories.DataBind();
}

if (date != null)
{
string entryUrl = Url.EntryUrl(entry);
string entryUrl = Url.EntryUrl(Entry);
if (date.Attributes["Format"] != null)
{
date.Text = string.Format(CultureInfo.InvariantCulture, "<a href=\"{0}\" title=\"{2}\">{1}</a>",
entryUrl, entry.DateSyndicated.ToString(date.Attributes["Format"]),
entryUrl, Entry.DateSyndicated.ToString(date.Attributes["Format"]),
Resources.EntryList_PermanentLink);
date.Attributes.Remove("Format");
}
else
{
date.Text = string.Format(CultureInfo.InvariantCulture, "<a href=\"{0}\" title=\"{2}\">{1}</a>",
entryUrl, entry.DateSyndicated.ToString("f"),
entryUrl, Entry.DateSyndicated.ToString("f"),
Resources.EntryList_PermanentLink);
}
}

if (commentCount != null)
{
if (Blog.CommentsEnabled && entry.AllowComments)
if (Blog.CommentsEnabled && Entry.AllowComments)
{
string entryUrl = Url.EntryUrl(entry);
if (entry.FeedBackCount == 0)
string entryUrl = Url.EntryUrl(Entry);
if (Entry.FeedBackCount == 0)
{
commentCount.Text = string.Format(LinkToComments, entryUrl, Resources.EntryList_AddComment,
string.Empty);
}
else if (entry.FeedBackCount == 1)
else if (Entry.FeedBackCount == 1)
{
commentCount.Text = string.Format(LinkToComments, entryUrl, Resources.EntryList_OneComment,
string.Empty);
}
else if (entry.FeedBackCount > 1)
else if (Entry.FeedBackCount > 1)
{
commentCount.Text = string.Format(LinkToComments, entryUrl, entry.FeedBackCount,
commentCount.Text = string.Format(LinkToComments, entryUrl, Entry.FeedBackCount,
Resources.EntryList_CommentsPlural);
}
}
}

BindEnclosure(entry);
BindEnclosure(Entry);

//Set Pingback/Trackback
if (PingBack == null)
Expand All @@ -136,20 +139,31 @@ protected override void OnLoad(EventArgs e)

if (PingBack != null)
{
PingBack.Text = TrackHelpers.GetPingPackTag(Url);
PingBack.Text = TrackHelpers.GetPingbackTag(Url, Entry);
}

if (TrackBack != null)
{
TrackBack.Text = TrackHelpers.TrackBackTag(entry, Blog, Url);
TrackBack.Text = TrackHelpers.TrackBackTag(Entry, Blog, Url);
}
DataBind();
}
else
{
//No post? Deleted? Help :)
Controls.Clear();
Controls.Add(new LiteralControl(Resources.ViewPost_EntryNotFound));
// Attempting to replace the content of this user control with
// a static message causes an exception if the skin control
// specifies server-side code using "<%= ... %>":
//
// "System.Web.HttpException: The Controls collection cannot be
// modified because the control contains code blocks (i.e. <%
// ... %>)."
//
// To avoid this, mimic a 404 error instead.
//
//Controls.Clear();
//Controls.Add(new LiteralControl(Resources.ViewPost_EntryNotFound));
throw new HttpException(404, "Post not found.");
}
}

Expand Down
18 changes: 12 additions & 6 deletions src/Subtext.Web/UI/Pages/SubTextMasterPage.cs
Expand Up @@ -99,13 +99,19 @@ public void InitializeControls(ISkinControlLoader controlLoader)
{
entryId = entry.Id;
}
var query = Query;
if (!String.IsNullOrEmpty(query))

// Allow errors in Lucene.Net.QueryParsers.QueryParser to be avoided by
// disabling the full text search engine in Web.config
if (FullTextSearchEngineSettings.Settings.IsEnabled == true)
{
var searchResults = SearchEngineService.Search(query, 5, Blog.Id, entryId);
if (searchResults.Any())
var query = Query;
if (!String.IsNullOrEmpty(query))
{
AddMoreResultsControl(searchResults, controlLoader, apnlCommentsWrapper);
var searchResults = SearchEngineService.Search(query, 5, Blog.Id, entryId);
if (searchResults.Any())
{
AddMoreResultsControl(searchResults, controlLoader, apnlCommentsWrapper);
}
}
}
}
Expand Down Expand Up @@ -220,7 +226,7 @@ public void InitializeBlogPage()
if (opensearch != null)
{
opensearch.Attributes.Add("href", Url.OpenSearchDescriptorUrl());
opensearch.Attributes.Add("Title", Blog.Title);
opensearch.Attributes.Add("title", Blog.Title);
}

if (RSSLink != null)
Expand Down
6 changes: 6 additions & 0 deletions src/Subtext.Web/Web.config
Expand Up @@ -18,6 +18,12 @@
<add name="subtextData" connectionString="Server=.\SQLEXPRESS;Database=SubtextData;Trusted_Connection=True;User Instance=false;" />
</connectionStrings>
<FullTextSearchEngineSettings type="Subtext.Framework.Configuration.FullTextSearchEngineSettings, Subtext.Framework">
<!-- Change the following to false to prevent related posts from automatically
being suggested when users find a post using an Internet search engine
(e.g. Google). This will also avoid potential errors in Lucene.Net
(e.g. Lucene.Net.QueryParsers.ParseException: Encountered " ":" ": "" at
line 1, column ... Was expecting one of: ...). -->
<IsEnabled>true</IsEnabled>
<Parameters>
<MinimumDocumentFrequency>10</MinimumDocumentFrequency>
</Parameters>
Expand Down