diff --git a/src/Nancy.Demo.Hosting.Aspnet/CustomErrorHandler.cs b/src/Nancy.Demo.Hosting.Aspnet/CustomErrorHandler.cs index bdbb335591..b760b2fe05 100644 --- a/src/Nancy.Demo.Hosting.Aspnet/CustomErrorHandler.cs +++ b/src/Nancy.Demo.Hosting.Aspnet/CustomErrorHandler.cs @@ -5,11 +5,12 @@ public class CustomErrorHandler : IErrorHandler { /// - /// Whether then + /// Check if the error handler can handle errors of the provided status code. /// /// Status code + /// The instance of the current request. /// True if handled, false otherwise - public bool HandlesStatusCode(HttpStatusCode statusCode) + public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) { return statusCode == HttpStatusCode.ImATeapot; } diff --git a/src/Nancy.Testing/PassThroughErrorHandler.cs b/src/Nancy.Testing/PassThroughErrorHandler.cs index 0d51d1ae23..84b7e6f724 100644 --- a/src/Nancy.Testing/PassThroughErrorHandler.cs +++ b/src/Nancy.Testing/PassThroughErrorHandler.cs @@ -5,7 +5,7 @@ namespace Nancy.Testing { public class PassThroughErrorHandler : IErrorHandler { - public bool HandlesStatusCode(HttpStatusCode statusCode) + public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) { return statusCode == HttpStatusCode.InternalServerError; } diff --git a/src/Nancy.Tests/Fakes/FakeRoutePatternMatchResult.cs b/src/Nancy.Tests/Fakes/FakeRoutePatternMatchResult.cs index 4f2177908b..7c020235bd 100644 --- a/src/Nancy.Tests/Fakes/FakeRoutePatternMatchResult.cs +++ b/src/Nancy.Tests/Fakes/FakeRoutePatternMatchResult.cs @@ -26,6 +26,8 @@ public FakeRoutePatternMatchResult(Action /// Initializes a new instance of the class. @@ -36,7 +33,7 @@ public void Should_return_default_binder_if_no_specific_binder_exists() A.CallTo(() => fakeBinder.CanBind(A.Ignored)).Returns(false); var locator = new DefaultModelBinderLocator(new IModelBinder[] { fakeBinder }, this.defaultBinder); - var result = locator.GetBinderForType(typeof(Model)); + var result = locator.GetBinderForType(typeof(Model), A.Ignored); result.ShouldBeSameAs(this.defaultBinder); } @@ -48,7 +45,7 @@ public void Should_not_return_a_binder_that_returns_false_for_canbind() A.CallTo(() => fakeBinder.CanBind(A.Ignored)).Returns(false); var locator = new DefaultModelBinderLocator(new IModelBinder[] { fakeBinder }, this.defaultBinder); - var result = locator.GetBinderForType(typeof(Model)); + var result = locator.GetBinderForType(typeof(Model), A.Ignored); result.ShouldNotBeSameAs(fakeBinder); } @@ -60,7 +57,7 @@ public void Should_return_a_binder_that_returns_true_for_canbind() A.CallTo(() => fakeBinder.CanBind(A.Ignored)).Returns(true); var locator = new DefaultModelBinderLocator(new IModelBinder[] { fakeBinder }, this.defaultBinder); - var result = locator.GetBinderForType(typeof(Model)); + var result = locator.GetBinderForType(typeof(Model), A.Ignored); result.ShouldBeSameAs(fakeBinder); } @@ -70,7 +67,7 @@ public void Should_be_able_to_bind_interfaces() { var binder = new InterfaceModelBinder(); var locator = new DefaultModelBinderLocator(new IModelBinder[] { binder }, this.defaultBinder); - var locatedBinder = locator.GetBinderForType(typeof(Concrete)); + var locatedBinder = locator.GetBinderForType(typeof(Concrete), A.Ignored); var result = locatedBinder.Bind(null, typeof(Concrete)) as IAmAnInterface; diff --git a/src/Nancy.Tests/Unit/ModelBinding/DynamicModelBinderAdapterFixture.cs b/src/Nancy.Tests/Unit/ModelBinding/DynamicModelBinderAdapterFixture.cs index 507eb13932..98b6254dbc 100644 --- a/src/Nancy.Tests/Unit/ModelBinding/DynamicModelBinderAdapterFixture.cs +++ b/src/Nancy.Tests/Unit/ModelBinding/DynamicModelBinderAdapterFixture.cs @@ -1,11 +1,8 @@ namespace Nancy.Tests.Unit.ModelBinding { using System; - using FakeItEasy; - using Nancy.ModelBinding; - using Xunit; public class DynamicModelBinderAdapterFixture @@ -13,61 +10,98 @@ public class DynamicModelBinderAdapterFixture [Fact] public void Should_throw_if_locator_is_null() { + // Given, When var result = Record.Exception(() => new DynamicModelBinderAdapter(null, new NancyContext())); + // Then result.ShouldBeOfType(typeof(ArgumentNullException)); } [Fact] public void Should_throw_if_context_is_null() { + // Given, When var result = Record.Exception(() => new DynamicModelBinderAdapter(A.Fake(), null)); + // Then result.ShouldBeOfType(typeof(ArgumentNullException)); } [Fact] public void Should_pass_type_to_locator_when_cast_implcitly() { + // Given var fakeModelBinder = A.Fake(); var returnModel = new Model(); A.CallTo(() => fakeModelBinder.Bind(null, null, null)).WithAnyArguments().Returns(returnModel); + var fakeLocator = A.Fake(); - A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored)).Returns(fakeModelBinder); + A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored, A.Ignored)).Returns(fakeModelBinder); dynamic adapter = new DynamicModelBinderAdapter(fakeLocator, new NancyContext()); + // When Model result = adapter; - A.CallTo(() => fakeLocator.GetBinderForType(typeof(Model))).MustHaveHappened(Repeated.Exactly.Once); + // Then + A.CallTo(() => fakeLocator.GetBinderForType(typeof(Model), A.Ignored)).MustHaveHappened(Repeated.Exactly.Once); + } + + [Fact] + public void Should_invoke_binder_with_context() + { + // Given + var context = new NancyContext(); + + var fakeModelBinder = A.Fake(); + var returnModel = new Model(); + A.CallTo(() => fakeModelBinder.Bind(null, null, null)).WithAnyArguments().Returns(returnModel); + + var fakeLocator = A.Fake(); + A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored, context)).Returns(fakeModelBinder); + dynamic adapter = new DynamicModelBinderAdapter(fakeLocator, context); + + // When + Model result = adapter; + + // Then + A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored, context)).MustHaveHappened(Repeated.Exactly.Once); } [Fact] public void Should_pass_type_to_locator_when_cast_explicitly() { + // Given var fakeModelBinder = A.Fake(); var returnModel = new Model(); A.CallTo(() => fakeModelBinder.Bind(null, null, null)).WithAnyArguments().Returns(returnModel); + var fakeLocator = A.Fake(); - A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored)).Returns(fakeModelBinder); + A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored, A.Ignored)).Returns(fakeModelBinder); dynamic adapter = new DynamicModelBinderAdapter(fakeLocator, new NancyContext()); + // When var result = (Model)adapter; - A.CallTo(() => fakeLocator.GetBinderForType(typeof(Model))).MustHaveHappened(Repeated.Exactly.Once); + // Then + A.CallTo(() => fakeLocator.GetBinderForType(typeof(Model), A.Ignored)).MustHaveHappened(Repeated.Exactly.Once); } [Fact] public void Should_return_object_from_binder_if_binder_doesnt_return_null() { + // Given var fakeModelBinder = A.Fake(); var returnModel = new Model(); A.CallTo(() => fakeModelBinder.Bind(null, null, null)).WithAnyArguments().Returns(returnModel); + var fakeLocator = A.Fake(); - A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored)).Returns(fakeModelBinder); + A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored, A.Ignored)).Returns(fakeModelBinder); dynamic adapter = new DynamicModelBinderAdapter(fakeLocator, new NancyContext()); + // When Model result = adapter; + // Then result.ShouldNotBeNull(); result.ShouldBeSameAs(returnModel); } @@ -75,12 +109,15 @@ public void Should_return_object_from_binder_if_binder_doesnt_return_null() [Fact] public void Should_throw_if_locator_does_not_return_binder() { + // Given var fakeLocator = A.Fake(); - A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored)).Returns(null); + A.CallTo(() => fakeLocator.GetBinderForType(A.Ignored, A.Ignored)).Returns(null); dynamic adapter = new DynamicModelBinderAdapter(fakeLocator, new NancyContext()); + // When var result = Record.Exception(() => (Model)adapter); + // Then result.ShouldBeOfType(typeof(ModelBindingException)); } } diff --git a/src/Nancy.Tests/Unit/NancyEngineFixture.cs b/src/Nancy.Tests/Unit/NancyEngineFixture.cs index aef7c9cfdd..44d3651180 100644 --- a/src/Nancy.Tests/Unit/NancyEngineFixture.cs +++ b/src/Nancy.Tests/Unit/NancyEngineFixture.cs @@ -32,7 +32,7 @@ public NancyEngineFixture() this.context = new NancyContext(); this.errorHandler = A.Fake(); - A.CallTo(() => errorHandler.HandlesStatusCode(A.Ignored)).Returns(false); + A.CallTo(() => errorHandler.HandlesStatusCode(A.Ignored, A.Ignored)).Returns(false); contextFactory = A.Fake(); A.CallTo(() => contextFactory.Create()).Returns(context); @@ -499,7 +499,7 @@ public void Should_ask_error_handler_if_it_can_handle_status_code() this.engine.HandleRequest(request); // Then - A.CallTo(() => this.errorHandler.HandlesStatusCode(A.Ignored)).MustHaveHappened(Repeated.Exactly.Once); + A.CallTo(() => this.errorHandler.HandlesStatusCode(A.Ignored, A.Ignored)).MustHaveHappened(Repeated.Exactly.Once); } [Fact] @@ -520,7 +520,7 @@ public void Should_invoke_error_handler_if_supported_status_code() { // Given var request = new Request("GET", "/", "http"); - A.CallTo(() => this.errorHandler.HandlesStatusCode(A.Ignored)).Returns(true); + A.CallTo(() => this.errorHandler.HandlesStatusCode(A.Ignored, A.Ignored)).Returns(true); // When this.engine.HandleRequest(request); diff --git a/src/Nancy.Tests/Unit/Routing/DefaultRoutePatternMatcherFixture.cs b/src/Nancy.Tests/Unit/Routing/DefaultRoutePatternMatcherFixture.cs index 9171a9855b..5bb56260ef 100644 --- a/src/Nancy.Tests/Unit/Routing/DefaultRoutePatternMatcherFixture.cs +++ b/src/Nancy.Tests/Unit/Routing/DefaultRoutePatternMatcherFixture.cs @@ -18,7 +18,7 @@ public DefaultRoutePatternMatcherFixture() public void Should_not_trim_trailing_slash_if_requesting_root() { // Given, When - var results = this.matcher.Match("/", "/"); + var results = this.matcher.Match("/", "/", null); // Then results.IsMatch.ShouldBeTrue(); @@ -28,7 +28,7 @@ public void Should_not_trim_trailing_slash_if_requesting_root() public void Should_ignore_trailing_slash_on_route_path() { // Given, When - var results = this.matcher.Match("/foo/bar", "/foo/bar/"); + var results = this.matcher.Match("/foo/bar", "/foo/bar/", null); // Then results.IsMatch.ShouldBeTrue(); @@ -38,7 +38,7 @@ public void Should_ignore_trailing_slash_on_route_path() public void Should_ignore_trailing_slash_on_request_uri() { // Given, When - var results = this.matcher.Match("/foo/bar/", "/foo/bar"); + var results = this.matcher.Match("/foo/bar/", "/foo/bar", null); // Then results.IsMatch.ShouldBeTrue(); @@ -48,17 +48,43 @@ public void Should_ignore_trailing_slash_on_request_uri() public void Should_return_match_result_when_paths_matched() { // Given, When - var results = this.matcher.Match("/foo/bar", "/foo/bar"); + var results = this.matcher.Match("/foo/bar", "/foo/bar", null); // Then results.IsMatch.ShouldBeTrue(); } + [Fact] + public void Should_return_match_result_with_context_of_current_request_when_paths_matched() + { + // Given + var context = new NancyContext(); + + // When + var results = this.matcher.Match("/foo/bar", "/foo/bar", context); + + // Then + results.Context.ShouldBeSameAs(context); + } + + [Fact] + public void Should_return_match_result_with_context_of_current_request_when_paths_do_not_match() + { + // Given + var context = new NancyContext(); + + // When + var results = this.matcher.Match("/foo/bar", "/bar/foo", context); + + // Then + results.Context.ShouldBeSameAs(context); + } + [Fact] public void Should_return_negative_match_result_when_paths_does_not_match() { // Given, When - var results = this.matcher.Match("/foo/bar", "/bar/foo"); + var results = this.matcher.Match("/foo/bar", "/bar/foo", null); // Then results.IsMatch.ShouldBeFalse(); @@ -68,7 +94,7 @@ public void Should_return_negative_match_result_when_paths_does_not_match() public void Should_be_case_insensitive_when_checking_for_match() { // Given, When - var results = this.matcher.Match("/FoO/baR", "/fOO/bAr"); + var results = this.matcher.Match("/FoO/baR", "/fOO/bAr", null); // Then results.IsMatch.ShouldBeTrue(); @@ -78,7 +104,7 @@ public void Should_be_case_insensitive_when_checking_for_match() public void Should_capture_parameters() { // Given, When - var results = this.matcher.Match("/foo/bar/baz", "/foo/{bar}/{baz}"); + var results = this.matcher.Match("/foo/bar/baz", "/foo/{bar}/{baz}", null); // Then ((string)results.Parameters["bar"]).ShouldEqual("bar"); @@ -89,7 +115,7 @@ public void Should_capture_parameters() public void Should_treat_parameters_as_greedy() { // Given, When - var results = this.matcher.Match("/foo/bar/baz", "/foo/{bar}"); + var results = this.matcher.Match("/foo/bar/baz", "/foo/{bar}", null); // Then ((string)results.Parameters["bar"]).ShouldEqual("bar/baz"); @@ -99,7 +125,7 @@ public void Should_treat_parameters_as_greedy() public void Should_allow_regex_in_route_definition_and_capture_specified_parameters() { // Given, When - var results = this.matcher.Match("/foo/1234", @"/(?foo)/(?\d{4})/"); + var results = this.matcher.Match("/foo/1234", @"/(?foo)/(?\d{4})/", null); // Then results.IsMatch.ShouldBeTrue(); @@ -111,7 +137,7 @@ public void Should_allow_regex_in_route_definition_and_capture_specified_paramet public void Should_allow_regex_in_route_definition_and_return_negative_result_when_it_does_not_match() { // Given, When - var results = this.matcher.Match("/foo/bar", @"/foo/(?[0-9]*)"); + var results = this.matcher.Match("/foo/bar", @"/foo/(?[0-9]*)", null); // Then results.IsMatch.ShouldBeFalse(); @@ -124,7 +150,7 @@ public void Should_not_url_decode_captured_parameters() var parameter = Uri.EscapeUriString("baa ram ewe{}"); // When - var results = this.matcher.Match("/foo/" + parameter, "/foo/{bar}"); + var results = this.matcher.Match("/foo/" + parameter, "/foo/{bar}", null); //Then ((string)results.Parameters["bar"]).ShouldEqual(parameter); @@ -137,7 +163,7 @@ public void Should_allow_all_of_the_unreserved_rfc_1738_characters_in_the_uri() const string parameter = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.!*'()"; // When - var results = this.matcher.Match("/foo/" + parameter, "/foo/{bar}"); + var results = this.matcher.Match("/foo/" + parameter, "/foo/{bar}", null); // Then ((string)results.Parameters["bar"]).ShouldEqual(parameter); @@ -150,7 +176,7 @@ public void Should_allow_underscore_in_parameter_key() const string parameter = "lol"; // When - var results = this.matcher.Match("/foo/" + parameter, "/foo/{b_ar}"); + var results = this.matcher.Match("/foo/" + parameter, "/foo/{b_ar}", null); // Then ((string)results.Parameters["b_ar"]).ShouldEqual(parameter); @@ -163,7 +189,7 @@ public void Should_capture_parameters_when_the_segment_contains_more_characters_ const string parameter = "filename"; // When - var results = this.matcher.Match("/foo/" + parameter + ".cshtml", "/foo/{name}.cshtml"); + var results = this.matcher.Match("/foo/" + parameter + ".cshtml", "/foo/{name}.cshtml", null); // Then ((string)results.Parameters["name"]).ShouldEqual(parameter); @@ -176,7 +202,7 @@ public void Should_capture_parameters_even_when_it_is_surrounded_by_additional_c const string parameter = "filename"; // When - var results = this.matcher.Match("/foo/bar" + parameter + ".cshtml", "/foo/bar{name}.cshtml"); + var results = this.matcher.Match("/foo/bar" + parameter + ".cshtml", "/foo/bar{name}.cshtml", null); // Then ((string)results.Parameters["name"]).ShouldEqual(parameter); @@ -186,7 +212,7 @@ public void Should_capture_parameters_even_when_it_is_surrounded_by_additional_c public void Should_capture_multiple_parameters() { // Given, When - var results = this.matcher.Match("/foo/filename.cshtml", "/foo/{name}.{format}"); + var results = this.matcher.Match("/foo/filename.cshtml", "/foo/{name}.{format}", null); // Then ((string)results.Parameters["name"]).ShouldEqual("filename"); @@ -197,7 +223,7 @@ public void Should_capture_multiple_parameters() public void Should_capture_multiple_parameters_that_are_surrounded_by_characters() { // Given, When - var results = this.matcher.Match("/foo/barfilename.cshtmlbaz", "/foo/bar{name}.{format}baz"); + var results = this.matcher.Match("/foo/barfilename.cshtmlbaz", "/foo/bar{name}.{format}baz", null); // Then ((string)results.Parameters["name"]).ShouldEqual("filename"); diff --git a/src/Nancy.Tests/Unit/Routing/DefaultRouteResolverFixture.cs b/src/Nancy.Tests/Unit/Routing/DefaultRouteResolverFixture.cs index bc6d1424f8..41916752dd 100644 --- a/src/Nancy.Tests/Unit/Routing/DefaultRouteResolverFixture.cs +++ b/src/Nancy.Tests/Unit/Routing/DefaultRouteResolverFixture.cs @@ -33,7 +33,7 @@ public DefaultRouteResolverFixture() A.CallTo(() => this.catalog.GetModuleByKey(A.Ignored, A.Ignored)).ReturnsLazily(() => this.expectedModule); this.matcher = A.Fake(); - A.CallTo(() => this.matcher.Match(A.Ignored, A.Ignored)).ReturnsLazily(x => + A.CallTo(() => this.matcher.Match(A.Ignored, A.Ignored, A.Ignored)).ReturnsLazily(x => new FakeRoutePatternMatchResult(c => { c.IsMatch(((string)x.Arguments[0]).Equals(((string)x.Arguments[1]))); @@ -110,7 +110,7 @@ public void Should_return_first_route_with_when_multiple_matches_are_available_a this.expectedModule = new FakeNancyModule(x => x.AddGetRoute("/foo/{bar}", this.expectedAction)); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true).AddParameter("bar", "fake value"))); // When @@ -132,10 +132,10 @@ public void Should_return_route_with_most_parameter_captures_when_multiple_match x.AddGetRoute("/foo/{bar}", "module-key-one-parameter"); }); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}", null)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true).AddParameter("bar", "fake value"))); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}/{foo}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}/{foo}", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true) .AddParameter("foo", "fake value") .AddParameter("bar", "fake value 2"))); @@ -164,13 +164,13 @@ public void Should_return_the_first_route_that_is_an_exact_match_over_any_other( x.AddGetRoute("/{foo}/{bar}", "module-key-two-parameters"); }); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/bar")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/bar", null)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true))); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}", null)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true).AddParameter("bar", "fake value"))); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}", null)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true) .AddParameter("foo", "fake value") .AddParameter("bar", "fake value"))); @@ -200,15 +200,15 @@ public void Should_return_the_route_with_the_most_specific_path_matches() this.expectedModule = new FakeNancyModule(x => x.AddGetRoute("/foo/bar/{two}", this.expectedAction)); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/bar/{two}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/bar/{two}", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true).AddParameter("two", "fake values"))); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}/{two}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}/{two}", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true) .AddParameter("bar", "fake values") .AddParameter("two", "fake values"))); - A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/foo/{bar}", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true).AddParameter("bar", "fake value"))); // When @@ -230,9 +230,9 @@ public void Should_choose_root_route_over_one_with_capture_if_requesting_root_ur x.AddGetRoute("/{name}", "module-key-second"); }); - A.CallTo(() => this.matcher.Match(request.Path, "/")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true))); - A.CallTo(() => this.matcher.Match(request.Path, "/{name}")).Returns( + A.CallTo(() => this.matcher.Match(request.Path, "/{name}", A.Ignored)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(true).AddParameter("name", "fake values"))); // When @@ -254,7 +254,22 @@ public void Should_invoke_pattern_matcher_with_request_uri() resolver.Resolve(context); // Then - A.CallTo(() => this.matcher.Match(request.Path, A.Ignored)).MustHaveHappened(); + A.CallTo(() => this.matcher.Match(request.Path, A.Ignored, A.Ignored)).MustHaveHappened(); + } + + [Fact] + public void Should_invoke_pattern_matcher_with_context() + { + // Given + var request = new FakeRequest("get", "/foo/bar"); + var context = new NancyContext { Request = request }; + var resolver = CreateResolver(x => x.AddGetRoute("/foo/bar")); + + // When + resolver.Resolve(context); + + // Then + A.CallTo(() => this.matcher.Match(A.Ignored, A.Ignored, context)).MustHaveHappened(); } [Fact] @@ -274,14 +289,15 @@ public void Should_invoke_pattern_matcher_for_all_entries_in_route_cache() resolver.Resolve(context); // Then - A.CallTo(() => this.matcher.Match(A.Ignored, "/foo/bar")).MustHaveHappened(); - A.CallTo(() => this.matcher.Match(A.Ignored, "/bar/foo")).MustHaveHappened(); - A.CallTo(() => this.matcher.Match(A.Ignored, "/foobar")).MustHaveHappened(); + A.CallTo(() => this.matcher.Match(A.Ignored, "/foo/bar", A.Ignored)).MustHaveHappened(); + A.CallTo(() => this.matcher.Match(A.Ignored, "/bar/foo", A.Ignored)).MustHaveHappened(); + A.CallTo(() => this.matcher.Match(A.Ignored, "/foobar", A.Ignored)).MustHaveHappened(); } [Fact] public void Should_ignore_method_casing_when_resolving_routes() { + // Given var request = new FakeRequest("GeT", "/foo/bar"); var context = new NancyContext { Request = request }; var resolver = CreateResolver(x => x.AddGetRoute("/foo/bar")); @@ -407,7 +423,7 @@ public void Should_return_notfoundroute_with_path_set_to_request_uri_when_route_ var context = new NancyContext { Request = request }; var resolver = CreateResolver(x => x.AddGetRoute("/bar/foo")); - A.CallTo(() => this.matcher.Match("/foo/bar", "/bar/foo")).Returns( + A.CallTo(() => this.matcher.Match("/foo/bar", "/bar/foo", null)).Returns( new FakeRoutePatternMatchResult(x => x.IsMatch(false))); // When diff --git a/src/Nancy.Tests/Unit/ViewEngines/DefaultRenderContextFixture.cs b/src/Nancy.Tests/Unit/ViewEngines/DefaultRenderContextFixture.cs index 2792e01c5a..153e77141e 100644 --- a/src/Nancy.Tests/Unit/ViewEngines/DefaultRenderContextFixture.cs +++ b/src/Nancy.Tests/Unit/ViewEngines/DefaultRenderContextFixture.cs @@ -194,5 +194,19 @@ public void Should_throw_if_context_does_not_contain_valid_csrf_token_and_its_re result.ShouldBeOfType(typeof(InvalidOperationException)); } + + [Fact] + public void Should_expose_context_from_viewlocationcontext() + { + // Given + var nancyContext = new NancyContext(); + var viewLocationContext = new ViewLocationContext { Context = nancyContext }; + + // When + var context = new DefaultRenderContext(null, null, viewLocationContext); + + // Then + context.Context.ShouldBeSameAs(nancyContext); + } } } \ No newline at end of file diff --git a/src/Nancy.Tests/Unit/ViewEngines/DefaultViewLocatorFixture.cs b/src/Nancy.Tests/Unit/ViewEngines/DefaultViewLocatorFixture.cs index b1acb806f6..999cfc023b 100644 --- a/src/Nancy.Tests/Unit/ViewEngines/DefaultViewLocatorFixture.cs +++ b/src/Nancy.Tests/Unit/ViewEngines/DefaultViewLocatorFixture.cs @@ -25,7 +25,7 @@ public void Should_return_null_if_locate_view_is_invoked_with_null_view_name() string viewName = null; // When - var result = this.viewLocator.LocateView(viewName); + var result = this.viewLocator.LocateView(viewName, null); // Then result.ShouldBeNull(); @@ -38,7 +38,7 @@ public void Should_return_null_if_locate_view_is_invoked_with_empty_view_name() var viewName = string.Empty; // When - var result = this.viewLocator.LocateView(viewName); + var result = this.viewLocator.LocateView(viewName, null); // Then result.ShouldBeNull(); @@ -54,7 +54,7 @@ public void Should_locate_view_when_only_name_is_provided() var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("index"); + var result = locator.LocateView("index", null); // Then result.ShouldBeSameAs(expectedView); @@ -71,7 +71,7 @@ public void Should_ignore_case_when_locating_view_based_on_name(string viewName) var locator = CreateViewLocator(cache); // When - var result = locator.LocateView(viewName); + var result = locator.LocateView(viewName, null); // Then result.ShouldBeSameAs(expectedView); @@ -87,7 +87,7 @@ public void Should_throw_ambiguousviewsexception_when_locating_view_by_name_retu var locator = CreateViewLocator(cache); // When - var exception = Record.Exception(() => locator.LocateView("index")); + var exception = Record.Exception(() => locator.LocateView("index", null)); // Then exception.ShouldBeOfType(); @@ -103,7 +103,7 @@ public void Should_throw_ambiguousviewsexception_when_locating_view_by_name_and_ var locator = CreateViewLocator(cache); // When - var exception = Record.Exception(() => locator.LocateView("index")); + var exception = Record.Exception(() => locator.LocateView("index", null)); // Then exception.ShouldBeOfType(); @@ -121,7 +121,7 @@ public void Should_set_message_on_ambiguousviewexception() const string expectedMessage = "This exception was thrown because multiple views were found. 2 view(s):\r\n\t/index.spark\r\n\t/index.html"; // When - var exception = Record.Exception(() => locator.LocateView("index")); + var exception = Record.Exception(() => locator.LocateView("index", null)); // Then exception.Message.ShouldEqual(expectedMessage); @@ -137,7 +137,7 @@ public void Should_return_null_when_view_cannot_be_located_using_name() var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("main"); + var result = locator.LocateView("main", null); // Then result.ShouldBeNull(); @@ -153,7 +153,7 @@ public void Should_locate_view_when_name_and_extension_are_provided() var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("index.cshtml"); + var result = locator.LocateView("index.cshtml", null); // Then result.ShouldBeSameAs(expectedView); @@ -170,7 +170,7 @@ public void Should_ignore_case_when_locating_view_based_on_name_and_extension(st var locator = CreateViewLocator(cache); // When - var result = locator.LocateView(viewName); + var result = locator.LocateView(viewName, null); // Then result.ShouldBeSameAs(expectedView); @@ -186,7 +186,7 @@ public void Should_return_null_when_view_cannot_be_located_using_name_and_extens var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("index.cshtml"); + var result = locator.LocateView("index.cshtml", null); // Then result.ShouldBeNull(); @@ -202,7 +202,7 @@ public void Should_locate_view_when_name_extension_and_location_are_provided() var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("views/sub/index.cshtml"); + var result = locator.LocateView("views/sub/index.cshtml", null); // Then result.ShouldBeSameAs(expectedView); @@ -219,7 +219,7 @@ public void Should_ignore_case_when_locating_view_based_on_name_extension_and_lo var locator = CreateViewLocator(cache); // When - var result = locator.LocateView(viewName); + var result = locator.LocateView(viewName, null); // Then result.ShouldBeSameAs(expectedView); @@ -235,7 +235,7 @@ public void Should_return_null_when_view_cannot_be_located_using_name_extension_ var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("views/feature/index.cshtml"); + var result = locator.LocateView("views/feature/index.cshtml", null); // Then result.ShouldBeNull(); @@ -251,7 +251,7 @@ public void Should_be_able_to_locate_view_by_name_when_two_views_with_same_name_ var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("views/sub/index"); + var result = locator.LocateView("views/sub/index", null); // Then result.ShouldBeSameAs(expectedView); @@ -267,7 +267,7 @@ public void Should_be_able_to_locate_view_by_name_and_extension_when_two_view_wi var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("views/index.cshtml"); + var result = locator.LocateView("views/index.cshtml", null); // Then result.ShouldBeSameAs(expectedView); @@ -283,7 +283,7 @@ public void Should_be_able_to_locate_view_by_name_when_two_views_with_same_name_ var locator = CreateViewLocator(cache); // When - var result = locator.LocateView("views/sub/index.cshtml"); + var result = locator.LocateView("views/sub/index.cshtml", null); // Then result.ShouldBeSameAs(expectedView); diff --git a/src/Nancy.Tests/Unit/ViewEngines/DefaultViewResolverFixture.cs b/src/Nancy.Tests/Unit/ViewEngines/DefaultViewResolverFixture.cs index 59d2d01350..9b0e215700 100644 --- a/src/Nancy.Tests/Unit/ViewEngines/DefaultViewResolverFixture.cs +++ b/src/Nancy.Tests/Unit/ViewEngines/DefaultViewResolverFixture.cs @@ -193,7 +193,24 @@ public void Should_invoke_viewlocator_with_viewname_from_conventions() resolver.GetViewLocation(viewName, null, this.viewLocationContext); // Then - A.CallTo(() => this.viewLocator.LocateView("bar.html")).MustHaveHappened(); + A.CallTo(() => this.viewLocator.LocateView("bar.html", A.Ignored)).MustHaveHappened(); + } + + [Fact] + public void Should_invoke_view_locator_with_context() + { + // Given + var resolver = new DefaultViewResolver( + this.viewLocator, + new ViewLocationConventions(new Func[] { + (name, model, path) => "bar.html" + })); + + // When + resolver.GetViewLocation("foo.html", null, this.viewLocationContext); + + // Then + A.CallTo(() => this.viewLocator.LocateView(A.Ignored, this.viewLocationContext.Context)).MustHaveHappened(); } [Fact] @@ -212,7 +229,7 @@ public void Should_not_invoke_viewlocator_when_conventions_returns_null_view_nam resolver.GetViewLocation(viewName, null, this.viewLocationContext); // Then - A.CallTo(() => this.viewLocator.LocateView(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => this.viewLocator.LocateView(A.Ignored, A.Ignored)).MustNotHaveHappened(); } [Fact] @@ -231,7 +248,7 @@ public void Should_not_invoke_viewlocator_when_conventions_returns_empty_view_na resolver.GetViewLocation(viewName, null, this.viewLocationContext); // Then - A.CallTo(() => this.viewLocator.LocateView(A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => this.viewLocator.LocateView(A.Ignored, A.Ignored)).MustNotHaveHappened(); } [Fact] @@ -265,7 +282,7 @@ public void Should_return_null_when_no_view_could_be_located() (name, model, path) => "bar.html" })); - A.CallTo(() => this.viewLocator.LocateView(A.Ignored)).Returns(null); + A.CallTo(() => this.viewLocator.LocateView(A.Ignored, A.Ignored)).Returns(null); // When var result = resolver.GetViewLocation(viewName, null, this.viewLocationContext); @@ -289,7 +306,7 @@ public void return_viewlocationresult_when_view_could_be_located() var locatedView = new ViewLocationResult("name", "location", "extension", GetEmptyContentReader()); - A.CallTo(() => this.viewLocator.LocateView(A.Ignored)).Returns(locatedView); + A.CallTo(() => this.viewLocator.LocateView(A.Ignored, A.Ignored)).Returns(locatedView); // When var result = resolver.GetViewLocation(viewName, null, this.viewLocationContext); diff --git a/src/Nancy.ViewEngines.Razor/HtmlHelpers.cs b/src/Nancy.ViewEngines.Razor/HtmlHelpers.cs index 20e7bd4083..d5a8e190e9 100644 --- a/src/Nancy.ViewEngines.Razor/HtmlHelpers.cs +++ b/src/Nancy.ViewEngines.Razor/HtmlHelpers.cs @@ -10,8 +10,8 @@ public class HtmlHelpers : IHtmlHelpers { private readonly TModel model; - public readonly RazorViewEngine engine; - public readonly IRenderContext renderContext; + private readonly RazorViewEngine engine; + private readonly IRenderContext renderContext; /// /// Initializes a new instance of the class. @@ -30,6 +30,7 @@ public HtmlHelpers(RazorViewEngine engine, IRenderContext renderContext, TModel /// Renders a partial with the given view name. /// /// Name of the view. + /// An representation of the partial. public IHtmlString Partial(string viewName) { return this.Partial(viewName, null); @@ -40,6 +41,7 @@ public IHtmlString Partial(string viewName) /// /// Name of the partial view. /// The model that is passed to the partial. + /// An representation of the partial. public IHtmlString Partial(string viewName, dynamic modelForPartial) { var view = this.renderContext.LocateView(viewName, modelForPartial); @@ -60,7 +62,7 @@ public IHtmlString Partial(string viewName, dynamic modelForPartial) /// Returns an html string composed of raw, non-encoded text. /// /// The text. - /// + /// An representation of the raw text. public IHtmlString Raw(string text) { return new NonEncodedHtmlString(text); @@ -69,7 +71,7 @@ public IHtmlString Raw(string text) /// /// Creates an anti-forgery token. /// - /// + /// An representation of the anti forgery token. public IHtmlString AntiForgeryToken() { var tokenKeyValue = this.renderContext.GetCsrfToken(); diff --git a/src/Nancy.ViewEngines.Razor/IHtmlHelpers.cs b/src/Nancy.ViewEngines.Razor/IHtmlHelpers.cs index c11b7ecbe0..77ea2b75a7 100644 --- a/src/Nancy.ViewEngines.Razor/IHtmlHelpers.cs +++ b/src/Nancy.ViewEngines.Razor/IHtmlHelpers.cs @@ -1,14 +1,16 @@ namespace Nancy.ViewEngines.Razor { /// - /// Defines the functionality of a html helper + /// Defines the functionality of a html helper. /// + /// The type of the model. public interface IHtmlHelpers { /// /// Renders a partial with the given view name. /// /// Name of the view. + /// An representation of the partial. IHtmlString Partial(string viewName); /// @@ -16,19 +18,20 @@ public interface IHtmlHelpers /// /// Name of the view. /// The model. + /// An representation of the partial. IHtmlString Partial(string viewName, dynamic model); /// /// Returns an html string composed of raw, non-encoded text. /// /// The text. - /// + /// An representation of the raw text. IHtmlString Raw(string text); /// /// Creates an anti-forgery token. /// - /// + /// An representation of the anti forgery token. IHtmlString AntiForgeryToken(); } } \ No newline at end of file diff --git a/src/Nancy/Diagnostics/IDiagnosticsProvider.cs b/src/Nancy/Diagnostics/IDiagnosticsProvider.cs index 48d3826901..8e3e432252 100644 --- a/src/Nancy/Diagnostics/IDiagnosticsProvider.cs +++ b/src/Nancy/Diagnostics/IDiagnosticsProvider.cs @@ -1,11 +1,26 @@ namespace Nancy.Diagnostics { + /// + /// Defines the functionality a diagnostics provider. + /// public interface IDiagnosticsProvider { + /// + /// Gets the name of the provider. + /// + /// A containing the name of the provider. string Name { get; } + /// + /// Gets the description of the provider. + /// + /// A containing the description of the provider. string Description { get; } + /// + /// Gets the object that contains the interactive diagnostics methods. + /// + /// An instance of the interactive diagnostics object. object DiagnosticObject { get; } } } \ No newline at end of file diff --git a/src/Nancy/Diagnostics/TestingDiagnosticProvider.cs b/src/Nancy/Diagnostics/TestingDiagnosticProvider.cs index 4583dfa805..d3a26ac47c 100644 --- a/src/Nancy/Diagnostics/TestingDiagnosticProvider.cs +++ b/src/Nancy/Diagnostics/TestingDiagnosticProvider.cs @@ -2,35 +2,38 @@ { public class TestingDiagnosticProvider : IDiagnosticsProvider { - private object diagObject; + private readonly object diagObject; public TestingDiagnosticProvider() { this.diagObject = new DiagObject(); } + /// + /// Gets the name of the provider. + /// + /// A containing the name of the provider. public string Name { - get - { - return "Testing Diagnostic Provider"; - } + get { return "Testing Diagnostic Provider"; } } + /// + /// Gets the description of the provider. + /// + /// A containing the description of the provider. public string Description { - get - { - return "Some testing methods that can be called to.. erm.. test things."; - } + get { return "Some testing methods that can be called to.. erm.. test things."; } } + /// + /// Gets the object that contains the interactive diagnostics methods. + /// + /// An instance of the interactive diagnostics object. public object DiagnosticObject { - get - { - return this.diagObject; - } + get { return this.diagObject; } } public class DiagObject diff --git a/src/Nancy/ErrorHandling/DefaultErrorHandler.cs b/src/Nancy/ErrorHandling/DefaultErrorHandler.cs index bbfaf4492e..3d714dd549 100644 --- a/src/Nancy/ErrorHandling/DefaultErrorHandler.cs +++ b/src/Nancy/ErrorHandling/DefaultErrorHandler.cs @@ -13,23 +13,26 @@ namespace Nancy.ErrorHandling /// public class DefaultErrorHandler : IErrorHandler { - private IDictionary errorPages; + private readonly IDictionary errorPages; - private IDictionary> expansionDelegates; + private readonly IDictionary> expansionDelegates; - private HttpStatusCode[] supportedStatusCodes = new[] { HttpStatusCode.NotFound, HttpStatusCode.InternalServerError}; + private readonly HttpStatusCode[] supportedStatusCodes = new[] { HttpStatusCode.NotFound, HttpStatusCode.InternalServerError}; + /// + /// Initializes a new instance of the type. + /// public DefaultErrorHandler() { this.errorPages = new Dictionary { - { HttpStatusCode.NotFound, this.LoadResource("404.html") }, - { HttpStatusCode.InternalServerError, this.LoadResource("500.html") }, + { HttpStatusCode.NotFound, LoadResource("404.html") }, + { HttpStatusCode.InternalServerError, LoadResource("500.html") }, }; this.expansionDelegates = new Dictionary> { - { HttpStatusCode.InternalServerError, this.PopulateErrorInfo} + { HttpStatusCode.InternalServerError, PopulateErrorInfo} }; } @@ -37,8 +40,9 @@ public DefaultErrorHandler() /// Whether then /// /// Status code + /// The instance of the current request. /// True if handled, false otherwise - public bool HandlesStatusCode(HttpStatusCode statusCode) + public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) { return this.supportedStatusCodes.Any(s => s == statusCode); } @@ -47,7 +51,7 @@ public bool HandlesStatusCode(HttpStatusCode statusCode) /// Handle the error code /// /// Status code - /// Current context + /// The instance of the current request. /// Nancy Response public void Handle(HttpStatusCode statusCode, NancyContext context) { @@ -74,10 +78,10 @@ public void Handle(HttpStatusCode statusCode, NancyContext context) errorPage = expansionDelegate.Invoke(statusCode, context, errorPage); } - this.ModifyResponse(statusCode, context, errorPage); + ModifyResponse(statusCode, context, errorPage); } - private void ModifyResponse(HttpStatusCode statusCode, NancyContext context, string errorPage) + private static void ModifyResponse(HttpStatusCode statusCode, NancyContext context, string errorPage) { if (context.Response == null) { @@ -94,7 +98,7 @@ private void ModifyResponse(HttpStatusCode statusCode, NancyContext context, str }; } - private string LoadResource(string filename) + private static string LoadResource(string filename) { var resourceStream = typeof(INancyEngine).Assembly.GetManifestResourceStream(String.Format("Nancy.ErrorHandling.Resources.{0}", filename)); @@ -109,7 +113,7 @@ private string LoadResource(string filename) } } - private string PopulateErrorInfo(HttpStatusCode httpStatusCode, NancyContext context, string templateContents) + private static string PopulateErrorInfo(HttpStatusCode httpStatusCode, NancyContext context, string templateContents) { return templateContents.Replace("[DETAILS]", StaticConfiguration.DisableErrorTraces ? String.Empty : context.GetExceptionDetails()); } diff --git a/src/Nancy/ErrorHandling/IErrorHandler.cs b/src/Nancy/ErrorHandling/IErrorHandler.cs index 948e2da21a..779c16eaae 100644 --- a/src/Nancy/ErrorHandling/IErrorHandler.cs +++ b/src/Nancy/ErrorHandling/IErrorHandler.cs @@ -6,11 +6,12 @@ namespace Nancy.ErrorHandling public interface IErrorHandler { /// - /// Whether then + /// Check if the error handler can handle errors of the provided status code. /// /// Status code + /// The instance of the current request. /// True if handled, false otherwise - bool HandlesStatusCode(HttpStatusCode statusCode); + bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context); /// /// Handle the error code diff --git a/src/Nancy/ModelBinding/DefaultModelBinderLocator.cs b/src/Nancy/ModelBinding/DefaultModelBinderLocator.cs index af75bd7d8a..5698868497 100644 --- a/src/Nancy/ModelBinding/DefaultModelBinderLocator.cs +++ b/src/Nancy/ModelBinding/DefaultModelBinderLocator.cs @@ -27,7 +27,6 @@ public class DefaultModelBinderLocator : IModelBinderLocator public DefaultModelBinderLocator(IEnumerable binders, IBinder fallbackBinder) { this.fallbackBinder = fallbackBinder; - this.binders = binders; } @@ -35,10 +34,11 @@ public DefaultModelBinderLocator(IEnumerable binders, IBinder fall /// Gets a binder for the given type /// /// Destination type to bind to + /// The instance of the current request. /// IModelBinder instance or null if none found - public IBinder GetBinderForType(Type modelType) + public IBinder GetBinderForType(Type modelType, NancyContext context) { - return this.binders.Where(modelBinder => modelBinder.CanBind(modelType)).FirstOrDefault() ?? this.fallbackBinder; + return this.binders.FirstOrDefault(modelBinder => modelBinder.CanBind(modelType)) ?? this.fallbackBinder; } } } \ No newline at end of file diff --git a/src/Nancy/ModelBinding/DynamicModelBinderAdapter.cs b/src/Nancy/ModelBinding/DynamicModelBinderAdapter.cs index 1ac77254a8..f3eb1df558 100644 --- a/src/Nancy/ModelBinding/DynamicModelBinderAdapter.cs +++ b/src/Nancy/ModelBinding/DynamicModelBinderAdapter.cs @@ -54,7 +54,7 @@ public DynamicModelBinderAdapter(IModelBinderLocator locator, NancyContext conte /// Provides information about the conversion operation. The binder.Type property provides the type to which the object must be converted. For example, for the statement (String)sampleObject in C# (CType(sampleObject, Type) in Visual Basic), where sampleObject is an instance of the class derived from the class, binder.Type returns the type. The binder.Explicit property provides information about the kind of conversion that occurs. It returns true for explicit conversion and false for implicit conversion.The result of the type conversion operation. public override bool TryConvert(ConvertBinder binder, out object result) { - var modelBinder = this.locator.GetBinderForType(binder.Type); + var modelBinder = this.locator.GetBinderForType(binder.Type, this.context); if (modelBinder == null) { @@ -63,7 +63,7 @@ public override bool TryConvert(ConvertBinder binder, out object result) result = modelBinder.Bind(this.context, binder.Type, this.blacklistedProperties); - return result != null ? true : base.TryConvert(binder, out result); + return result != null || base.TryConvert(binder, out result); } } } \ No newline at end of file diff --git a/src/Nancy/ModelBinding/IModelBinderLocator.cs b/src/Nancy/ModelBinding/IModelBinderLocator.cs index 3c020919f1..faba310ed9 100644 --- a/src/Nancy/ModelBinding/IModelBinderLocator.cs +++ b/src/Nancy/ModelBinding/IModelBinderLocator.cs @@ -11,7 +11,8 @@ public interface IModelBinderLocator /// Gets a binder for the given type /// /// Destination type to bind to + /// The instance of the current request. /// IModelBinder instance or null if none found - IBinder GetBinderForType(Type modelType); + IBinder GetBinderForType(Type modelType, NancyContext context); } } \ No newline at end of file diff --git a/src/Nancy/NancyEngine.cs b/src/Nancy/NancyEngine.cs index 416105c6b7..f927432988 100644 --- a/src/Nancy/NancyEngine.cs +++ b/src/Nancy/NancyEngine.cs @@ -198,7 +198,7 @@ private void CheckErrorHandler(NancyContext context) return; } - foreach (var errorHandler in this.errorHandlers.Where(e => e.HandlesStatusCode(context.Response.StatusCode))) + foreach (var errorHandler in this.errorHandlers.Where(e => e.HandlesStatusCode(context.Response.StatusCode, null))) { errorHandler.Handle(context.Response.StatusCode, context); } diff --git a/src/Nancy/Routing/DefaultRouteCacheProvider.cs b/src/Nancy/Routing/DefaultRouteCacheProvider.cs index b9043349cb..0de1966866 100755 --- a/src/Nancy/Routing/DefaultRouteCacheProvider.cs +++ b/src/Nancy/Routing/DefaultRouteCacheProvider.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Linq; - using Nancy.Diagnostics; /// @@ -16,31 +15,29 @@ public class DefaultRouteCacheProvider : IRouteCacheProvider, IDiagnosticsProvid { protected readonly Func RouteCacheFactory; - private object diagnosticObject; - + /// + /// Gets the name of the provider. + /// + /// A containing the name of the provider. public string Name { - get - { - return "Route Cache"; - } + get { return "Route Cache"; } } + /// + /// Gets the description of the provider. + /// + /// A containing the description of the provider. public string Description { - get - { - return "Provides methods for viewing and querying the route cache."; - } + get { return "Provides methods for viewing and querying the route cache."; } } - public object DiagnosticObject - { - get - { - return this.diagnosticObject; - } - } + /// + /// Gets the object that contains the interactive diagnostics methods. + /// + /// An instance of the interactive diagnostics object. + public object DiagnosticObject { get; private set; } /// /// Initializes a new instance of the DefaultRouteCacheProvider class. @@ -50,7 +47,7 @@ public DefaultRouteCacheProvider(Func routeCacheFactory) { this.RouteCacheFactory = routeCacheFactory; - this.diagnosticObject = new RouteCacheDiagnostics(this); + this.DiagnosticObject = new RouteCacheDiagnostics(this); } /// diff --git a/src/Nancy/Routing/DefaultRoutePatternMatcher.cs b/src/Nancy/Routing/DefaultRoutePatternMatcher.cs index b68d96dfdb..0ea9054293 100644 --- a/src/Nancy/Routing/DefaultRoutePatternMatcher.cs +++ b/src/Nancy/Routing/DefaultRoutePatternMatcher.cs @@ -20,8 +20,9 @@ public class DefaultRoutePatternMatcher : IRoutePatternMatcher /// /// The path that was requested. /// The route pattern that the requested path should be attempted to be matched with. + /// The instance for the current request. /// An instance, containing the outcome of the match. - public IRoutePatternMatchResult Match(string requestedPath, string routePath) + public IRoutePatternMatchResult Match(string requestedPath, string routePath, NancyContext context) { var routePathPattern = this.matcherCache.GetOrAdd(routePath, s => BuildRegexMatcher(routePath)); @@ -37,7 +38,8 @@ public IRoutePatternMatchResult Match(string requestedPath, string routePath) return new RoutePatternMatchResult( matches.Any(), - GetParameters(routePathPattern, matches)); + GetParameters(routePathPattern, matches), + context); } private static string TrimTrailingSlashFromRequestedPath(string requestedPath) diff --git a/src/Nancy/Routing/DefaultRouteResolver.cs b/src/Nancy/Routing/DefaultRouteResolver.cs index dda7cf6d2f..f6bb7b0d0e 100644 --- a/src/Nancy/Routing/DefaultRouteResolver.cs +++ b/src/Nancy/Routing/DefaultRouteResolver.cs @@ -135,7 +135,7 @@ private ResolveResults Resolve(string path, NancyContext context, IRouteCache ro routes = routes.Filter(context, "Path did not match", (ctx, route) => { var validationResult = - this.routePatternMatcher.Match(path, route.Item3.Path); + this.routePatternMatcher.Match(path, route.Item3.Path, context); var routeToReturn = (validationResult.IsMatch) ? new RouteCandidate(route.Item1, route.Item2, route.Item3, validationResult) : route; @@ -246,16 +246,28 @@ public ResolveResults() public Dictionary> Rejected { get; set; } } + /// + /// Gets the name of the provider. + /// + /// A containing the name of the provider. public string Name { get { return "Default route resolver"; } } + /// + /// Gets the description of the provider. + /// + /// A containing the description of the provider. public string Description { get { return "A description"; } } + /// + /// Gets the object that contains the interactive diagnostics methods. + /// + /// An instance of the interactive diagnostics object. public object DiagnosticObject { get { return new DefaultRouteResolverDiagnosticsProvider(this); } diff --git a/src/Nancy/Routing/IRoutePatternMatchResult.cs b/src/Nancy/Routing/IRoutePatternMatchResult.cs index 7c3fb5108a..a78bfd3577 100644 --- a/src/Nancy/Routing/IRoutePatternMatchResult.cs +++ b/src/Nancy/Routing/IRoutePatternMatchResult.cs @@ -5,6 +5,12 @@ /// public interface IRoutePatternMatchResult { + /// + /// Gets the that was active when the result was produced. + /// + /// A instance. + NancyContext Context { get; } + /// /// Gets a value idicating wether or not a match was made. /// diff --git a/src/Nancy/Routing/IRoutePatternMatcher.cs b/src/Nancy/Routing/IRoutePatternMatcher.cs index f152aecb5f..2aad6d64ec 100644 --- a/src/Nancy/Routing/IRoutePatternMatcher.cs +++ b/src/Nancy/Routing/IRoutePatternMatcher.cs @@ -11,7 +11,8 @@ public interface IRoutePatternMatcher /// /// The path that was requested. /// The route pattern that the requested path should be attempted to be matched with. + /// The instance for the current request. /// An instance, containing the outcome of the match. - IRoutePatternMatchResult Match(string requestedPath, string routePath); + IRoutePatternMatchResult Match(string requestedPath, string routePath, NancyContext context); } } \ No newline at end of file diff --git a/src/Nancy/Routing/MethodNotAllowedRoute.cs b/src/Nancy/Routing/MethodNotAllowedRoute.cs index ff48c15eac..b2f765fd9a 100644 --- a/src/Nancy/Routing/MethodNotAllowedRoute.cs +++ b/src/Nancy/Routing/MethodNotAllowedRoute.cs @@ -8,6 +8,13 @@ /// This is equal to sending back the 405 HTTP status code. public class MethodNotAllowedRoute : Route { + /// + /// Initializes a new instance of the type, for the + /// specifed , and . + /// + /// The path of the route. + /// The HTTP method of the route. + /// The HTTP methods that can be used to invoke the route. public MethodNotAllowedRoute(string path, string method, IEnumerable allowedMethods) : base(method, path, null, x => CreateMethodNotAllowedResponse(allowedMethods)) { diff --git a/src/Nancy/Routing/NotFoundRoute.cs b/src/Nancy/Routing/NotFoundRoute.cs index c9129dc064..46cb627049 100644 --- a/src/Nancy/Routing/NotFoundRoute.cs +++ b/src/Nancy/Routing/NotFoundRoute.cs @@ -6,6 +6,12 @@ /// This is equal to sending back the 404 HTTP status code. public class NotFoundRoute : Route { + /// + /// Initializes a new instance of the type, for the + /// specified and . + /// + /// The HTTP method of the route. + /// The path of the route. public NotFoundRoute(string method, string path) : base(method, path, null, x => new NotFoundResponse()) { diff --git a/src/Nancy/Routing/Route.cs b/src/Nancy/Routing/Route.cs index 45471147e1..238c53b45c 100644 --- a/src/Nancy/Routing/Route.cs +++ b/src/Nancy/Routing/Route.cs @@ -2,8 +2,16 @@ { using System; + /// + /// Stores information about a declared route in Nancy. + /// public class Route { + /// + /// Initializes a new instance of the type, with the specified . + /// + /// + /// The action that should take place when the route is invoked. public Route(RouteDescription description, Func action) { if (action == null) @@ -15,15 +23,35 @@ public Route(RouteDescription description, Func action) this.Action = action; } + /// + /// Initializes a new instance of the type, with the specified definition. + /// + /// The HTTP method that the route is declared for. + /// The path that the route is declared for. + /// A condition that needs to be satisfied inorder for the route to be eligiable for invocation. + /// The action that should take place when the route is invoked. public Route (string method, string path, Func condition, Func action) : this(new RouteDescription(method, path, condition), action) { } + /// + /// Gets or sets the action that should take place when the route is invoked. + /// + /// A that represents the action of the route. public Func Action { get; set; } + /// + /// Gets the description of the route. + /// + /// A instance. public RouteDescription Description { get; private set; } + /// + /// Invokes the route with the provided . + /// + /// A that contains the parameters that should be passed to the route. + /// A instance. public Response Invoke(DynamicDictionary parameters) { return this.Action.Invoke(parameters); diff --git a/src/Nancy/Routing/RoutePatternMatchResult.cs b/src/Nancy/Routing/RoutePatternMatchResult.cs index 4d8ecdd7b5..05637abc87 100644 --- a/src/Nancy/Routing/RoutePatternMatchResult.cs +++ b/src/Nancy/Routing/RoutePatternMatchResult.cs @@ -10,12 +10,20 @@ public class RoutePatternMatchResult : IRoutePatternMatchResult /// /// A value indicating if the result was a match or not. /// A instance containing the parameters and values that was captured in the match. - public RoutePatternMatchResult(bool isMatch, DynamicDictionary parameters) + /// The instance of the current request. + public RoutePatternMatchResult(bool isMatch, DynamicDictionary parameters, NancyContext context) { this.IsMatch = isMatch; this.Parameters = parameters; + this.Context = context; } + /// + /// Gets the that was active when the result was produced. + /// + /// A instance. + public NancyContext Context { get; private set; } + /// /// Gets a value idicating wether or not a match was made. /// diff --git a/src/Nancy/ViewEngines/DefaultRenderContext.cs b/src/Nancy/ViewEngines/DefaultRenderContext.cs index f4b354aac2..26451aea77 100644 --- a/src/Nancy/ViewEngines/DefaultRenderContext.cs +++ b/src/Nancy/ViewEngines/DefaultRenderContext.cs @@ -29,6 +29,15 @@ public DefaultRenderContext(IViewResolver viewResolver, IViewCache viewCache, Vi this.viewLocationContext = viewLocationContext; } + /// + /// Gets the context of the current request. + /// + /// A instance. + public NancyContext Context + { + get { return this.viewLocationContext.Context; } + } + /// /// Gets the view cache that is used by Nancy. /// diff --git a/src/Nancy/ViewEngines/DefaultViewLocationCache.cs b/src/Nancy/ViewEngines/DefaultViewLocationCache.cs index 24e6406c20..206cb0dd4b 100644 --- a/src/Nancy/ViewEngines/DefaultViewLocationCache.cs +++ b/src/Nancy/ViewEngines/DefaultViewLocationCache.cs @@ -1,10 +1,9 @@ -using Nancy.Diagnostics; - namespace Nancy.ViewEngines { using System.Collections; using System.Collections.Generic; using System.Linq; + using Nancy.Diagnostics; public class DefaultViewLocationCache : IViewLocationCache, IDiagnosticsProvider { @@ -47,19 +46,28 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } + /// + /// Gets the name of the provider. + /// + /// A containing the name of the provider. public string Name { get { return "View location cache"; } } + /// + /// Gets the description of the provider. + /// + /// A containing the description of the provider. public string Description { - get - { - return "Provides methods for viewing and manipulating the view cache."; - } + get { return "Provides methods for viewing and manipulating the view cache."; } } + /// + /// Gets the object that contains the interactive diagnostics methods. + /// + /// An instance of the interactive diagnostics object. public object DiagnosticObject { get { return new DefaultViewLocationCacheDiagnostics(this); } diff --git a/src/Nancy/ViewEngines/DefaultViewLocator.cs b/src/Nancy/ViewEngines/DefaultViewLocator.cs index 9b606246d3..fb9d83b02f 100644 --- a/src/Nancy/ViewEngines/DefaultViewLocator.cs +++ b/src/Nancy/ViewEngines/DefaultViewLocator.cs @@ -21,8 +21,9 @@ public DefaultViewLocator(IViewLocationCache viewLocationCache) /// Gets the location of the view defined by the parameter. /// /// Name of the view to locate. + /// The instance for the current request. /// A instance if the view could be located; otherwise . - public ViewLocationResult LocateView(string viewName) + public ViewLocationResult LocateView(string viewName, NancyContext context) { if (string.IsNullOrEmpty(viewName)) { diff --git a/src/Nancy/ViewEngines/DefaultViewResolver.cs b/src/Nancy/ViewEngines/DefaultViewResolver.cs index 379e783889..8d1785ab24 100644 --- a/src/Nancy/ViewEngines/DefaultViewResolver.cs +++ b/src/Nancy/ViewEngines/DefaultViewResolver.cs @@ -66,7 +66,7 @@ public ViewLocationResult GetViewLocation(string viewName, dynamic model, ViewLo viewLocationContext.Context.Trace.TraceLog.WriteLog(x => x.AppendLine(string.Concat("[DefaultViewResolver] Attempting to locate view using convention '", conventionBasedViewName, "'"))); var locatedView = - this.viewLocator.LocateView(conventionBasedViewName); + this.viewLocator.LocateView(conventionBasedViewName, viewLocationContext.Context); if (locatedView != null) { diff --git a/src/Nancy/ViewEngines/IRenderContext.cs b/src/Nancy/ViewEngines/IRenderContext.cs index 07c7ecda75..74a3e4f9a1 100644 --- a/src/Nancy/ViewEngines/IRenderContext.cs +++ b/src/Nancy/ViewEngines/IRenderContext.cs @@ -7,6 +7,12 @@ namespace Nancy.ViewEngines /// public interface IRenderContext { + /// + /// Gets the context of the current request. + /// + /// A instance. + NancyContext Context { get; } + /// /// Gets the view cache that is used by Nancy. /// diff --git a/src/Nancy/ViewEngines/IViewLocator.cs b/src/Nancy/ViewEngines/IViewLocator.cs index af7edf78b3..58a21a6072 100644 --- a/src/Nancy/ViewEngines/IViewLocator.cs +++ b/src/Nancy/ViewEngines/IViewLocator.cs @@ -9,7 +9,8 @@ public interface IViewLocator : IHideObjectMembers /// Gets the location of the view defined by the parameter. /// /// Name of the view to locate. + /// The instance for the current request. /// A instance if the view could be located; otherwise . - ViewLocationResult LocateView(string viewName); + ViewLocationResult LocateView(string viewName, NancyContext context); } } \ No newline at end of file