Skip to content

Commit

Permalink
migrated fubumvc.conventions project into core
Browse files Browse the repository at this point in the history
  • Loading branch information
jmarnold committed Sep 2, 2011
1 parent 6ff6be7 commit 9054064
Show file tree
Hide file tree
Showing 18 changed files with 436 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@ packaging/release
*.swp
output
output/*

*.dotCover
2 changes: 2 additions & 0 deletions src/FubuMVC.Core/FubuMVC.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<Compile Include="Continuations\FubuContinuation.cs" />
<Compile Include="Continuations\ContinuationType.cs" />
<Compile Include="Continuations\IContinuationDirector.cs" />
<Compile Include="FubuRegistry.OutOfBoxConventions.cs" />
<Compile Include="CurrentRequest.cs" />
<Compile Include="Diagnostics\IObserverImporter.cs" />
<Compile Include="Diagnostics\RecordingOutputWriter.cs" />
Expand Down Expand Up @@ -198,6 +199,7 @@
<Compile Include="Registration\AssemblyScanner.cs" />
<Compile Include="Registration\AssemblyScanningExtensions.cs" />
<Compile Include="Registration\ConnectImplementationsServiceRegistrationConvention.cs" />
<Compile Include="Registration\Conventions\HandlersUrlPolicy.cs" />
<Compile Include="Registration\Conventions\MethodToUrlBuilder.cs" />
<Compile Include="Registration\Conventions\MissingRouteInputPolicy.cs" />
<Compile Include="Registration\Conventions\PartialRequestConvention.cs" />
Expand Down
38 changes: 38 additions & 0 deletions src/FubuMVC.Core/FubuRegistry.OutOfBoxConventions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using FubuMVC.Core.Registration.Conventions;

namespace FubuMVC.Core
{
public partial class FubuRegistry
{
public void ApplyHandlerConventions()
{
ApplyHandlerConventions(GetType());
}

public void ApplyHandlerConventions<T>()
where T : class
{
ApplyHandlerConventions(typeof(T));
}

public void ApplyHandlerConventions(params Type[] markerTypes)
{
markerTypes
.Each(t => Applies
.ToAssembly(t.Assembly));

includeHandlers(markerTypes);

Routes
.UrlPolicy(new HandlersUrlPolicy(markerTypes));
}

private void includeHandlers(params Type[] markerTypes)
{
markerTypes.Each(markerType => Actions.IncludeTypes(t => t.Namespace.StartsWith(markerType.Namespace)));
Actions.IncludeMethods(action => action.Method.Name == HandlersUrlPolicy.METHOD);
}
}
}
120 changes: 120 additions & 0 deletions src/FubuMVC.Core/Registration/Conventions/HandlersUrlPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using FubuCore;
using FubuCore.Reflection;
using FubuMVC.Core.Diagnostics;
using FubuMVC.Core.Registration.Nodes;
using FubuMVC.Core.Registration.Routes;

namespace FubuMVC.Core.Registration.Conventions
{
public class HandlersUrlPolicy : IUrlPolicy
{
public const string HANDLER = "Handler";
public const string METHOD = "Execute";
public static readonly Regex HandlerExpression = new Regex("_[hH]andler", RegexOptions.Compiled);

private readonly IEnumerable<Type> _markerTypes;

public HandlersUrlPolicy(params Type[] markerTypes)
{
_markerTypes = markerTypes;
}

public bool Matches(ActionCall call, IConfigurationObserver log)
{
if ((!call.HandlerType.Name.ToLower().EndsWith(HANDLER.ToLower()) && !HandlerExpression.IsMatch(call.HandlerType.Name))
|| call.Method.HasAttribute<UrlPatternAttribute>())
{
return false;
}

log.RecordCallStatus(call, "Matched on {0}".ToFormat(GetType().Name));
return true;
}

public IRouteDefinition Build(ActionCall call)
{
var routeDefinition = call.ToRouteDefinition();
var strippedNamespace = stripNamespace(call);

if (strippedNamespace != call.HandlerType.Namespace)
{
if (!strippedNamespace.Contains("."))
{
routeDefinition.Append(breakUpCamelCaseWithHypen(strippedNamespace));
}
else
{
var patternParts = strippedNamespace.Split(new[] { "." }, StringSplitOptions.None);
foreach (var patternPart in patternParts)
{
routeDefinition.Append(breakUpCamelCaseWithHypen(patternPart.Trim()));
}
}
}

var handlerName = call.HandlerType.Name;
var match = HandlerExpression.Match(handlerName);
if (match.Success && MethodToUrlBuilder.Matches(handlerName))
{
// We're forcing handlers to end with "_handler" in this case
handlerName = handlerName.Substring(0, match.Index);
var properties = call.HasInput
? new TypeDescriptorCache().GetPropertiesFor(call.InputType()).Keys
: new string[0];

MethodToUrlBuilder.Alter(routeDefinition, handlerName, properties, text => { });

if (call.HasInput)
{
routeDefinition.ApplyInputType(call.InputType());
}
}
else
{
// Otherwise we're expecting something like "GetHandler"
var httpMethod = call.HandlerType.Name.Replace(HANDLER, string.Empty);
routeDefinition.ConstrainToHttpMethods(httpMethod.ToUpper());
}

return routeDefinition;
}

private string stripNamespace(ActionCall call)
{
var strippedNamespace = "";

_markerTypes
.Each(marker =>
{
strippedNamespace = call
.HandlerType
.Namespace
.Replace(marker.Namespace + ".", string.Empty);
});

return strippedNamespace;
}

private static string breakUpCamelCaseWithHypen(string input)
{
var routeBuilder = new StringBuilder();
for (int i = 0; i < input.Length; ++i)
{
if (i != 0 && char.IsUpper(input[i]))
{
routeBuilder.Append("-");
}

routeBuilder.Append(input[i]);
}

return routeBuilder
.ToString()
.ToLower();
}
}
}
1 change: 1 addition & 0 deletions src/FubuMVC.HelloSpark/FubuMVC.HelloSpark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="HelloSparkRegistry.cs" />
<Compile Include="Hello\get_Name_handler.cs" />
<Compile Include="SampleHtmlConventions.cs" />
<Compile Include="Controllers\Air\AirController.cs" />
<Compile Include="Controllers\Earth\EarthController.cs" />
Expand Down
17 changes: 17 additions & 0 deletions src/FubuMVC.HelloSpark/Hello/get_Name_handler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using FubuCore;

namespace FubuMVC.HelloSpark.Hello
{
public class get_Name_handler
{
public string Execute(SayHelloRequestModel request)
{
return "Hello, {0}".ToFormat(request.Name);
}
}

public class SayHelloRequestModel
{
public string Name { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/FubuMVC.HelloSpark/HelloSparkRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public HelloSparkRegistry()
Actions
.IncludeClassesSuffixedWithController();

ApplyHandlerConventions();

Routes
.HomeIs<AirController>(c => c.TakeABreath())
.IgnoreControllerNamespaceEntirely()
Expand Down
10 changes: 10 additions & 0 deletions src/FubuMVC.Tests/FubuMVC.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@
<Compile Include="Registration\BehaviorNodeTester.cs" />
<Compile Include="Registration\Conventions\AllowRoleAttributeTester.cs" />
<Compile Include="Registration\Conventions\AuthorizedByAttributeConventionTester.cs" />
<Compile Include="Registration\Conventions\HandlersConventionTester.cs" />
<Compile Include="Registration\Conventions\HandlersUrlPolicyTester.cs" />
<Compile Include="Registration\Conventions\Handlers\HandlersMarker.cs" />
<Compile Include="Registration\Conventions\Handlers\JsonResponse.cs" />
<Compile Include="Registration\Conventions\Handlers\HandlersObjectMother.cs" />
<Compile Include="Registration\Conventions\Handlers\Posts\ComplexRoute\GetHandler.cs" />
<Compile Include="Registration\Conventions\Handlers\Posts\Create\GetHandler.cs" />
<Compile Include="Registration\Conventions\Handlers\Posts\get_Year_Month_Title_handler.cs" />
<Compile Include="Registration\Conventions\Handlers\Posts\UrlPatternHandler.cs" />
<Compile Include="Registration\Conventions\Handlers\SampleController.cs" />
<Compile Include="Registration\Conventions\MethodToUrlBuilderTester.cs" />
<Compile Include="Registration\Conventions\PartialRegistrationConventionTester.cs" />
<Compile Include="Registration\Conventions\RenderStatusCodeConventionTester.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace FubuMVC.Tests.Registration.Conventions.Handlers
{
public class HandlersMarker
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using FubuMVC.Core.Registration.Nodes;
using FubuMVC.Tests.Registration.Conventions.Handlers.Posts;
using FubuMVC.Tests.Registration.Conventions.Handlers.Posts.Create;

namespace FubuMVC.Tests.Registration.Conventions.Handlers
{
public class HandlersObjectMother
{
public static ActionCall HandlerCall()
{
return ActionCall.For<GetHandler>(h => h.Execute(new CreatePostRequestModel()));
}
public static ActionCall ComplexHandlerCall()
{
return ActionCall.For<Handlers.Posts.ComplexRoute.GetHandler>(h => h.Execute());
}

public static ActionCall NonHandlerCall()
{
return ActionCall.For<SampleController>(c => c.Hello());
}

public static ActionCall HandlerWithAttributeCall()
{
return ActionCall.For<UrlPatternHandler>(h => h.Execute());
}

public static ActionCall HandlerWithRouteInput()
{
return ActionCall.For<get_Year_Month_Title_handler>(h => h.Execute(new ViewPostRequestModel()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace FubuMVC.Tests.Registration.Conventions.Handlers
{
public class JsonResponse
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace FubuMVC.Tests.Registration.Conventions.Handlers.Posts.ComplexRoute
{
public class GetHandler
{
public JsonResponse Execute()
{
return new JsonResponse();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace FubuMVC.Tests.Registration.Conventions.Handlers.Posts.Create
{
public class GetHandler
{
public JsonResponse Execute(CreatePostRequestModel requestModel)
{
throw new NotImplementedException();
}
}

public class CreatePostRequestModel // HTTP GET
{
}

public class CreatePostInputModel // HTTP Post
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using FubuMVC.Core;

namespace FubuMVC.Tests.Registration.Conventions.Handlers.Posts
{
public class UrlPatternHandler
{
[UrlPattern("some-crazy-url/as-a-subfolder")]
public JsonResponse Execute()
{
return new JsonResponse();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace FubuMVC.Tests.Registration.Conventions.Handlers.Posts
{
public class get_Year_Month_Title_handler
{
public PostDetailsViewModel Execute(ViewPostRequestModel request)
{
return new PostDetailsViewModel();
}
}

public class ViewPostRequestModel
{
public int Year { get; set; }
public int Month { get; set; }
public string Title { get; set; }
}

public class PostDetailsViewModel
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace FubuMVC.Tests.Registration.Conventions.Handlers
{
public class SampleController
{
public JsonResponse Hello()
{
return new JsonResponse();
}
}
}
Loading

0 comments on commit 9054064

Please sign in to comment.