diff --git a/.gitignore b/.gitignore index 913a11e5..62fa9116 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# NuGet Packages Directory +packages + +.vs/ bin/ obj/ .idea/ @@ -10,6 +14,9 @@ Thumbs.db *.obj *.exe *.pdb +*.pidb +*.userprefs +*.test-cache *.user *.aps *.pch @@ -34,3 +41,9 @@ obj/ _ReSharper*/ [Tt]est[Rr]esult* App_Data/ +.DS_Store +*.resharper.user +*.suo +*.user +*.ncrunch* +*.gpState \ No newline at end of file diff --git a/LICENSE b/LICENSE index 9daf02d2..5df016fa 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2011, Demis Bellot, ServiceStack. +Copyright (c) 2007-2016, Demis Bellot, ServiceStack. http://www.servicestack.net All rights reserved. diff --git a/README.md b/README.md index 26cb80cf..a5b63bf4 100644 --- a/README.md +++ b/README.md @@ -4,44 +4,43 @@ for twitter updates. #Example Projects built with [ServiceStack](https://github.com/ServiceStack/ServiceStack), [C# RedisClient](https://github.com/ServiceStack/ServiceStack.Redis), [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite), etc -## Live Demo +## [Download](https://github.com/ServiceStack/ServiceStack.Examples/archive/master.zip) -A live demo and tutorials are available at the following locations: +Download the tarball: -### [Backbone.js TODO app with REST and Redis backend](http://servicestack.net/Backbone.Todos/) -[![Backbone REST and Redis TODOs](http://servicestack.net/showcase/img/todos-400x350.png)](http://servicestack.net/Backbone.Todos/) +[https://github.com/ServiceStack/ServiceStack.Examples/archive/master.zip](https://github.com/ServiceStack/ServiceStack.Examples/archive/master.zip) -### [Creating a Hello World Web service from scratch](http://servicestack.net/ServiceStack.Hello/) -[![ServiceStacks Hello, World!](http://servicestack.net/showcase/img/hello-400x350.png)](http://servicestack.net/ServiceStack.Hello/) +or clone this repo to download the source: -### [GitHub-like browser to maange remote filesystem over REST](http://servicestack.net/RestFiles/) -[![GitHub-like REST Files](http://servicestack.net/showcase/img/restfiles-400x350.png)](http://servicestack.net/RestFiles/) + git clone git://github.com/ServiceStack/ServiceStack.Examples.git -### [Creating a StackOverflow-like app in Redis](http://servicestack.net/RedisStackOverflow/) -[![Redis StackOverflow](http://servicestack.net/showcase/img/redisstackoverflow-400x350.png)](http://servicestack.net/RedisStackOverflow/) -### [Complete REST Web service example](http://servicestack.net/ServiceStack.MovieRest/) -[![REST at the Movies!](http://servicestack.net/showcase/img/movierest-400x350.png)](http://servicestack.net/ServiceStack.MovieRest/) +## [Live Demos](https://github.com/ServiceStackApps/LiveDemos) -### [Calling Web Services with Ajax](http://servicestack.net/ServiceStack.Examples.Clients/) -[![Ajax Example](http://servicestack.net/showcase/img/ajaxexample-400x350.png)](http://servicestack.net/ServiceStack.Examples.Clients/) +[Live demos](https://github.com/ServiceStackApps/LiveDemos) and tutorials are available at the following locations: -### Other examples -* [Calling Web Services with Mono Touch](http://www.servicestack.net/monotouch/remote-info/) -* [Calling Web Services using Silverlight](http://servicestack.net/ServiceStack.Examples.Clients/Silverlight.htm) -* [Calling SOAP 1.1 Web Service Examples](http://servicestack.net/ServiceStack.Examples.Clients/Soap11.aspx) -* [Calling SOAP 1.2 Web Service Examples](http://servicestack.net/ServiceStack.Examples.Clients/Soap12.aspx) +### [Backbone.js TODO app with REST and Redis backend](http://todos.servicestack.net) +[![Backbone REST and Redis TODOs](http://servicestack.net/showcase/img/todos-400x350.png)](http://todos.servicestack.net) + +### [Creating a Hello World Web service from scratch](http://mono.servicestack.net/ServiceStack.Hello/) +[![ServiceStacks Hello, World!](http://servicestack.net/showcase/img/hello-400x350.png)](http://mono.servicestack.net/ServiceStack.Hello/) -_All live examples hosted on CentOS/Nginx/FastCGI/Mono_ +### [GitHub-like browser to manage remote filesystem over REST](http://restfiles.servicestack.net) +[![GitHub-like REST Files](http://servicestack.net/showcase/img/restfiles-400x350.png)](http://restfiles.servicestack.net) -# Download +### [Creating a StackOverflow-like app in Redis](http://redisstackoverflow.servicestack.net) +[![Redis StackOverflow](http://servicestack.net/showcase/img/redisstackoverflow-400x350.png)](http://redisstackoverflow.servicestack.net) -You can find the latest releases for download at: +### [Northwind dataset services](http://northwind.servicestack.net) +[![Redis StackOverflow](http://servicestack.net/showcase/img/northwind-400x350.png)](http://northwind.servicestack.net) -* [ServiceStack.Examples/downloads](https://github.com/ServiceStack/ServiceStack.Examples/downloads) +### Other examples +* [Calling Web Services with Mono Touch](http://mono.servicestack.net/monotouch/remote-info/) +* [Calling Web Services using Silverlight](http://mono.servicestack.net/ServiceStack.Examples.Clients/Silverlight.htm) +* [Calling SOAP 1.1 Web Service Examples](http://mono.servicestack.net/ServiceStack.Examples.Clients/Soap11.aspx) +* [Calling SOAP 1.2 Web Service Examples](http://mono.servicestack.net/ServiceStack.Examples.Clients/Soap12.aspx) ### Troubleshooting -- Since the example project uses 32bit Sqlite.dll, on a 64 bit machine you must set IIS to run 32bit apps (in the App Domain config) - +- Since the example project uses 32bit Sqlite.dll, on a 64bit machine you must set IIS to run 32bit apps (in the App Domain config) diff --git a/lib/Mono.Data.Sqlite.dll b/lib/Mono.Data.Sqlite.dll deleted file mode 100644 index dad79f06..00000000 Binary files a/lib/Mono.Data.Sqlite.dll and /dev/null differ diff --git a/lib/ServiceStack.Common.dll b/lib/ServiceStack.Common.dll deleted file mode 100644 index 910e3bbe..00000000 Binary files a/lib/ServiceStack.Common.dll and /dev/null differ diff --git a/lib/ServiceStack.Interfaces.dll b/lib/ServiceStack.Interfaces.dll deleted file mode 100644 index b5fd9f88..00000000 Binary files a/lib/ServiceStack.Interfaces.dll and /dev/null differ diff --git a/lib/ServiceStack.OrmLite.SqlServer.dll b/lib/ServiceStack.OrmLite.SqlServer.dll deleted file mode 100644 index 21b56d9f..00000000 Binary files a/lib/ServiceStack.OrmLite.SqlServer.dll and /dev/null differ diff --git a/lib/ServiceStack.OrmLite.Sqlite.dll b/lib/ServiceStack.OrmLite.Sqlite.dll deleted file mode 100644 index 5961f3c9..00000000 Binary files a/lib/ServiceStack.OrmLite.Sqlite.dll and /dev/null differ diff --git a/lib/ServiceStack.OrmLite.dll b/lib/ServiceStack.OrmLite.dll deleted file mode 100644 index 2b2638a5..00000000 Binary files a/lib/ServiceStack.OrmLite.dll and /dev/null differ diff --git a/lib/ServiceStack.Redis.dll b/lib/ServiceStack.Redis.dll deleted file mode 100644 index 78ae57bf..00000000 Binary files a/lib/ServiceStack.Redis.dll and /dev/null differ diff --git a/lib/ServiceStack.ServiceInterface.dll b/lib/ServiceStack.ServiceInterface.dll deleted file mode 100644 index 5f544843..00000000 Binary files a/lib/ServiceStack.ServiceInterface.dll and /dev/null differ diff --git a/lib/ServiceStack.Text.dll b/lib/ServiceStack.Text.dll deleted file mode 100644 index cc52cebd..00000000 Binary files a/lib/ServiceStack.Text.dll and /dev/null differ diff --git a/lib/ServiceStack.dll b/lib/ServiceStack.dll deleted file mode 100644 index e14ec19e..00000000 Binary files a/lib/ServiceStack.dll and /dev/null differ diff --git a/lib/sqlite3.dll b/lib/sqlite3.dll deleted file mode 100644 index 321d48d3..00000000 Binary files a/lib/sqlite3.dll and /dev/null differ diff --git a/lib/tests/Moq.dll b/lib/tests/Moq.dll deleted file mode 100644 index abcb72ee..00000000 Binary files a/lib/tests/Moq.dll and /dev/null differ diff --git a/lib/tests/Moq.xml b/lib/tests/Moq.xml deleted file mode 100644 index a29e2306..00000000 --- a/lib/tests/Moq.xml +++ /dev/null @@ -1,2930 +0,0 @@ - - - - Moq - - - - - A that returns an empty default value - for invocations that do not have expectations or return values, with loose mocks. - This is the default behavior for a mock. - - - - - Interface to be implemented by classes that determine the - default value of non-expected invocations. - - - - - Provides a value for the given member and arguments. - - The member to provide a default - value for. - Optional arguments passed in - to the call that requires a default value. - - - Type to mock, which can be an interface or a class. - - Provides a mock implementation of . - - - Only abstract and virtual members of classes can be mocked. - - The behavior of the mock with regards to the expectations and the actual calls is determined - by the optional that can be passed to the - constructor. - - - - The following example shows setting expectations with specific values - for method invocations: - - //setup - data - var order = new Order(TALISKER, 50); - var mock = new Mock<IWarehouse>(); - - //setup - expectations - mock.Expect(x => x.HasInventory(TALISKER, 50)).Returns(true); - - //exercise - order.Fill(mock.Object); - - //verify - Assert.True(order.IsFilled); - - The following example shows how to use the class - to specify conditions for arguments instead of specific values: - - //setup - data - var order = new Order(TALISKER, 50); - var mock = new Mock<IWarehouse>(); - - //setup - expectations - //shows how to expect a value within a range - mock.Expect(x => x.HasInventory( - It.IsAny<string>(), - It.IsInRange(0, 100, Range.Inclusive))) - .Returns(false); - - //shows how to throw for unexpected calls. contrast with the "verify" approach of other mock libraries. - mock.Expect(x => x.Remove( - It.IsAny<string>(), - It.IsAny<int>())) - .Throws(new InvalidOperationException()); - - //exercise - order.Fill(mock.Object); - - //verify - Assert.False(order.IsFilled); - - - - - - Helper interface used to hide the base - members from the fluent API to make it much cleaner - in Visual Studio intellisense. - - - - - - - - - - - - - - - - - Adds an interface implementation to the mock, - allowing expectations to be set for it. - - - This method can only be called before the first use - of the mock property, at which - point the runtime type has already been generated - and no more interfaces can be added to it. - - Also, must be an - interface and not a class, which must be specified - when creating the mock instead. - - - The mock type - has already been generated by accessing the property. - The specified - is not an interface. - - The following example creates a mock for the main interface - and later adds to it to verify - it's called by the consumer code: - - var mock = new Mock<IProcessor>(); - mock.Expect(x => x.Execute("ping")); - - // add IDisposable interface - var disposable = mock.As<IDisposable>(); - disposable.Expect(d => d.Dispose()).Verifiable(); - - - Type of interface to cast the mock to. - - - - Sets an expectation on the mocked type for a call to - to a value returning method. - - Type of the return value. Typically omitted as it can be inferred from the expression. - - If more than one expectation is set for the same method or property, - the latest one wins and is the one that will be executed. - - Lambda expression that specifies the expected method invocation. - - - mock.Expect(x => x.HasInventory("Talisker", 50)).Returns(true); - - - - - - Sets an expectation on the mocked type for a call to - to a void method. - - - If more than one expectation is set for the same method or property, - the latest one wins and is the one that will be executed. - - Lambda expression that specifies the expected method invocation. - - - var mock = new Mock<IProcessor>(); - mock.Expect(x => x.Execute("ping")); - - - - - - Sets an expectation on the mocked type for a call to - to a property getter. - - - If more than one expectation is set for the same property getter, - the latest one wins and is the one that will be executed. - - Type of the property. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected property getter. - - - mock.ExpectGet(x => x.Suspended) - .Returns(true); - - - - - - Sets an expectation on the mocked type for a call to - to a property setter. - - - If more than one expectation is set for the same property setter, - the latest one wins and is the one that will be executed. - - Type of the property. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected property setter. - - - mock.ExpectSet(x => x.Suspended); - - - - - - Sets an expectation on the mocked type for a call to - to a property setter with a specific value. - - - More than one expectation can be set for the setter with - different values. - - Type of the property. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected property setter. - The value expected to be set for the property. - - - mock.ExpectSet(x => x.Suspended, true); - - - - - - Implements . - - - - - Implements . - - - - - Verifies that a specific invocation matching the given - expression was performed on the mock. Use in conjuntion - with the default . - - - This example assumes that the mock has been used, - and later we want to verify that a given invocation - with specific parameters was performed: - - var mock = new Mock<IProcessor>(); - // exercise mock - //... - // Will throw if the test code didn't call Execute with a "ping" string argument. - mock.Verify(proc => proc.Execute("ping")); - - - The invocation was not performed on the mock. - Expression to verify. - - - - Verifies that a specific invocation matching the given - expression was performed on the mock. Use in conjuntion - with the default . - - - This example assumes that the mock has been used, - and later we want to verify that a given invocation - with specific parameters was performed: - - var mock = new Mock<IWarehouse>(); - // exercise mock - //... - // Will throw if the test code didn't call HasInventory. - mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50)); - - - The invocation was not performed on the mock. - Expression to verify. - Type of return value from the expression. - - - - Verifies that a property was read on the mock. - Use in conjuntion with the default . - - - This example assumes that the mock has been used, - and later we want to verify that a given property - was retrieved from it: - - var mock = new Mock<IWarehouse>(); - // exercise mock - //... - // Will throw if the test code didn't retrieve the IsClosed property. - mock.VerifyGet(warehouse => warehouse.IsClosed); - - - The invocation was not performed on the mock. - Expression to verify. - Type of the property to verify. Typically omitted as it can - be inferred from the expression's return type. - - - - Verifies that a property has been set on the mock. - Use in conjuntion with the default . - - - This example assumes that the mock has been used, - and later we want to verify that a given invocation - with specific parameters was performed: - - var mock = new Mock<IWarehouse>(); - // exercise mock - //... - // Will throw if the test code didn't set the IsClosed property. - mock.VerifySet(warehouse => warehouse.IsClosed); - - - The invocation was not performed on the mock. - Expression to verify. - Type of the property to verify. Typically omitted as it can - be inferred from the expression's return type. - - - - Verifies that a property has been set on the mock to the given value. - Use in conjuntion with the default . - - - This example assumes that the mock has been used, - and later we want to verify that a given invocation - with specific parameters was performed: - - var mock = new Mock<IWarehouse>(); - // exercise mock - //... - // Will throw if the test code didn't set the IsClosed property to true - mock.VerifySet(warehouse => warehouse.IsClosed, true); - - - The invocation was not performed on the mock. - Expression to verify. - The value that should have been set on the property. - Type of the property to verify. Typically omitted as it can - be inferred from the expression's return type. - - - - Exposes the mocked object instance. - - - - - Specifies the behavior to use when returning default values for - unexpected invocations. - - - - - Behavior of the mock, according to the value set in the constructor. - - - - - Implements the fluent API. - - - - - Defines the Callback verb and overloads. - - - - - Specifies a callback to invoke when the method is called. - - Callback method to invoke. - - The following example specifies a callback to set a boolean - value that can be used later: - - bool called = false; - mock.Expect(x => x.Execute()) - .Callback(() => called = true); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Argument type of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation argument value. - - Notice how the specific string argument is retrieved by simply declaring - it as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute(It.IsAny<string>())) - .Callback((string command) => Console.WriteLine(command)); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation arguments values. - - Notice how the specific arguments are retrieved by simply declaring - them as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>())) - .Callback((string arg1, string arg2) => Console.WriteLine(arg1 + arg2)); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Type of the third argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation arguments values. - - Notice how the specific arguments are retrieved by simply declaring - them as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>(), - It.IsAny<int>())) - .Callback((string arg1, string arg2, int arg3) => Console.WriteLine(arg1 + arg2 + arg3)); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Type of the third argument of the invoked method. - Type of the fourth argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation arguments values. - - Notice how the specific arguments are retrieved by simply declaring - them as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>(), - It.IsAny<int>(), - It.IsAny<bool>())) - .Callback((string arg1, string arg2, int arg3, bool arg4) => Console.WriteLine(arg1 + arg2 + arg3 + arg4)); - - - - - - Defines occurrence members to constraint expectations. - - - - - The expected invocation can happen at most once. - - - - var mock = new Mock<ICommand>(); - mock.Expect(foo => foo.Execute("ping")) - .AtMostOnce(); - - - - - - The expected invocation can happen at most specified number of times. - - - - var mock = new Mock<ICommand>(); - mock.Expect(foo => foo.Execute("ping")) - .AtMost( 5 ); - - - - - - Defines the Verifiable verb. - - - - - Marks the expectation as verifiable, meaning that a call - to will check if this particular - expectation was met. - - - The following example marks the expectation as verifiable: - - mock.Expect(x => x.Execute("ping")) - .Returns(true) - .Verifiable(); - - - - - - Defines the Raises verb. - - - - - Specifies the mocked event that will be raised - when the expectation is met. - - The mocked event, retrieved from - or . - - The event args to pass when raising the event. - - The following example shows how to set an expectation that will - raise an event when it's met: - - var mock = new Mock<IContainer>(); - // create handler to associate with the event to raise - var handler = mock.CreateEventHandler(); - // associate the handler with the event to raise - mock.Object.Added += handler; - // set the expectation and the handler to raise - mock.Expect(add => add.Add(It.IsAny<string>(), It.IsAny<object>())) - .Raises(handler, EventArgs.Empty); - - - - - - Specifies the mocked event that will be raised - when the expectation is met. - - The mocked event, retrieved from - or . - - A function that will build the - to pass when raising the event. - - - - - Specifies the mocked event that will be raised - when the expectation is met. - - The mocked event, retrieved from - or . - - A function that will build the - to pass when raising the event. - Type of the argument received by the expected invocation. - - - - - Specifies the mocked event that will be raised - when the expectation is met. - - The mocked event, retrieved from - or . - - A function that will build the - to pass when raising the event. - Type of the first argument received by the expected invocation. - Type of the second argument received by the expected invocation. - - - - - Specifies the mocked event that will be raised - when the expectation is met. - - The mocked event, retrieved from - or . - - A function that will build the - to pass when raising the event. - Type of the first argument received by the expected invocation. - Type of the second argument received by the expected invocation. - Type of the third argument received by the expected invocation. - - - - - Specifies the mocked event that will be raised - when the expectation is met. - - The mocked event, retrieved from - or . - - A function that will build the - to pass when raising the event. - Type of the first argument received by the expected invocation. - Type of the second argument received by the expected invocation. - Type of the third argument received by the expected invocation. - Type of the fourth argument received by the expected invocation. - - - - - Marks a method as a matcher, which allows complete replacement - of the built-in class with your own argument - matching rules. - - - The argument matching is used to determine whether a concrete - invocation in the mock matches a given expectation. This - matching mechanism is fully extensible. - - There are two parts of a matcher: the compiler matcher - and the runtime matcher. - - - Compiler matcher - Used to satisfy the compiler requirements for the - argument. Needs to be a method optionally receiving any arguments - you might need for the matching, but with a return type that - matches that of the argument. - - Let's say I want to match a lists of orders that contains - a particular one. I might create a compiler matcher like the following: - - - public static class Orders - { - [Matcher] - public static IEnumerable<Order> Contains(Order order) - { - return null; - } - } - - Now we can invoke this static method instead of an argument in an - invocation: - - var order = new Order { ... }; - var mock = new Mock<IRepository<Order>>(); - - mock.Expect(x => x.Save(Orders.Contains(order))) - .Throws<ArgumentException>(); - - Note that the return value from the compiler matcher is irrelevant. - This method will never be called, and is just used to satisfy the - compiler and to signal Moq that this is not a method that we want - to be invoked at runtime. - - - - Runtime matcher - - The runtime matcher is the one that will actually perform evaluation - when the test is run, and is defined by convention to have the - same signature as the compiler matcher, but where the return - value is the first argument to the call, which contains the - object received by the actual invocation at runtime: - - public static bool Contains(IEnumerable<Order> orders, Order order) - { - return orders.Contains(order); - } - - At runtime, the mocked method will be invoked with a specific - list of orders. This value will be passed to this runtime - matcher as the first argument, while the second argument is the - one specified in the expectation (x.Save(Orders.Contains(order))). - - The boolean returned determines whether the given argument has been - matched. If all arguments to the expected method are matched, then - the expectation is verified. - - - - - - Using this extensible infrastructure, you can easily replace the entire - set of matchers with your own. You can also avoid the - typical (and annoying) lengthy expressions that result when you have - multiple arguments that use generics. - - - The following is the complete example explained above: - - public static class Orders - { - [Matcher] - public static IEnumerable<Order> Contains(Order order) - { - return null; - } - - public static bool Contains(IEnumerable<Order> orders, Order order) - { - return orders.Contains(order); - } - } - - And the concrete test using this matcher: - - var order = new Order { ... }; - var mock = new Mock<IRepository<Order>>(); - - mock.Expect(x => x.Save(Orders.Contains(order))) - .Throws<ArgumentException>(); - - // use mock, invoke Save, and have the matcher filter. - - - - - - Casts the expression to a lambda expression, removing - a cast if there's any. - - - - - Casts the body of the lambda expression to a . - - If the body is not a method call. - - - - Converts the body of the lambda expression into the referenced by it. - - - - - Checks whether the body of the lambda expression is a property access. - - - - - Checks whether the expression is a property access. - - - - - Checks whether the body of the lambda expression is a property indexer, which is true - when the expression is an whose - has - equal to . - - - - - Checks whether the expression is a property indexer, which is true - when the expression is an whose - has - equal to . - - - - - Creates an expression that casts the given expression to the - type. - - - - - TODO: remove this code when https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=331583 - is fixed. - - - - - Base class for visitors of expression trees. - - - Provides the functionality of the internal visitor base class that - comes with Linq. - Matt's comments on the implementation: - - In this variant there is only one visitor class that dispatches calls to the general - Visit function out to specific VisitXXX methods corresponding to different node types. - Note not every node type gets it own method, for example all binary operators are - treated in one VisitBinary method. The nodes themselves do not directly participate - in the visitation process. They are treated as just data. - The reason for this is that the quantity of visitors is actually open ended. - You can write your own. Therefore no semantics of visiting is coupled into the node classes. - It’s all in the visitors. The default visit behavior for node XXX is baked into the base - class’s version of VisitXXX. - - - Another variant is that all VisitXXX methods return a node. - The Expression tree nodes are immutable. In order to change the tree you must construct - a new one. The default VisitXXX methods will construct a new node if any of its sub-trees change. - If no changes are made then the same node is returned. That way if you make a change - to a node (by making a new node) deep down in a tree, the rest of the tree is rebuilt - automatically for you. - - See: http://blogs.msdn.com/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspx. - - Matt Warren: http://blogs.msdn.com/mattwar - Documented by InSTEDD: http://www.instedd.org - - - - Default constructor used by derived visitors. - - - - - Visits the , determining which - of the concrete Visit methods to call. - - - - - Visits the generic , determining and - calling the appropriate Visit method according to the - , which will result - in calls to , - or . - - - - - - - Visits the initializer by - calling the for the - . - - - - - Visits the expression by - calling with the expression. - - - - - Visits the by calling - with the , - and - expressions. - - - - - Visits the by calling - with the - expression. - - - - - Visits the , by default returning the - same without further behavior. - - - - - Visits the by calling - with the , - and - expressions. - - - - - Visits the returning it - by default without further behavior. - - - - - Visits the by calling - with the - expression. - - - - - Visits the by calling - with the expression, - and then with the . - - - - - - - Visits the by iterating - the list and visiting each in it. - - - - - - - Visits the by calling - with the expression. - - - - - - - Visits the by calling - with the . - - - - - - - Visits the by calling - with the - . - - - - - - - Visits the by - calling for each in the - collection. - - - - - - - Visits the by - calling for each - in the collection. - - - - - - - Visits the by calling - with the expression. - - - - - - - Visits the by calling - with the - expressions. - - - - - - - Visits the by calling - with the - expression, then with the - . - - - - - Visits the by calling - with the - expression, and then with the - . - - - - - - - Visits the by calling - with the - expressions. - - - - - - - Visits the by calling - with the - expressions. - - - - - - - Provides partial evaluation of subtrees, whenever they can be evaluated locally. - - Matt Warren: http://blogs.msdn.com/mattwar - Documented by InSTEDD: http://www.instedd.org - - - - Performs evaluation and replacement of independent sub-trees - - The root of the expression tree. - A function that decides whether a given expression - node can be part of the local function. - A new tree with sub-trees evaluated and replaced. - - - - Performs evaluation and replacement of independent sub-trees - - The root of the expression tree. - A new tree with sub-trees evaluated and replaced. - - - - Evaluates and replaces sub-trees when first candidate is reached (top-down) - - - - - Performs bottom-up analysis to determine which nodes can possibly - be part of an evaluated sub-tree. - - - - - Checks an argument to ensure it isn't null. - - The argument value to check. - The name of the argument. - - - - Checks a string argument to ensure it isn't null or empty. - - The argument value to check. - The name of the argument. - - - - Defines the Returns verb for property get expectations. - - Type of the property. - - - - Base interface for . - - - - - Specifies the value to return. - - The value to return, or . - - Return a true value from the property getter call: - - mock.ExpectGet(x => x.Suspended) - .Returns(true); - - - - - - Specifies a function that will calculate the value to return for the property. - - The function that will calculate the return value. - - Return a calculated value when the property is retrieved: - - mock.ExpectGet(x => x.Suspended) - .Returns(() => returnValues[0]); - - The lambda expression to retrieve the return value is lazy-executed, - meaning that its value may change depending on the moment the property - is retrieved and the value the returnValues array has at - that moment. - - - - - Defines the Callback verb for property getter expectations. - - - Type of the property. - - - - Specifies a callback to invoke when the property is retrieved. - - Callback method to invoke. - - Invokes the given callback with the property value being set. - - mock.ExpectGet(x => x.Suspended) - .Callback(() => called = true) - .Returns(true); - - - - - - Implements the fluent API. - - - - - Implements the fluent API. - - - - - Defines the Returns verb. - - Type of the return value from the expression. - - - - Specifies the value to return. - - The value to return, or . - - Return a true value from the method call: - - mock.Expect(x => x.Execute("ping")) - .Returns(true); - - - - - - Specifies a function that will calculate the value to return from the method. - - The function that will calculate the return value. - - Return a calculated value when the method is called: - - mock.Expect(x => x.Execute("ping")) - .Returns(() => returnValues[0]); - - The lambda expression to retrieve the return value is lazy-executed, - meaning that its value may change depending on the moment the method - is executed and the value the returnValues array has at - that moment. - - - - - Specifies a function that will calculate the value to return from the method, - retrieving the arguments for the invocation. - - Type of the argument of the invoked method. - The function that will calculate the return value. - - Return a calculated value which is evaluated lazily at the time of the invocation. - - The lookup list can change between invocations and the expectation - will return different values accordingly. Also, notice how the specific - string argument is retrieved by simply declaring it as part of the lambda - expression: - - - mock.Expect(x => x.Execute(It.IsAny<string>())) - .Returns((string command) => returnValues[command]); - - - - - - Specifies a function that will calculate the value to return from the method, - retrieving the arguments for the invocation. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - The function that will calculate the return value. - - Return a calculated value which is evaluated lazily at the time of the invocation. - - The return value is calculated from the value of the actual method invocation arguments. - Notice how the arguments are retrieved by simply declaring them as part of the lambda - expression: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>())) - .Returns((string arg1, string arg2) => arg1 + arg2); - - - - - - Specifies a function that will calculate the value to return from the method, - retrieving the arguments for the invocation. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Type of the third argument of the invoked method. - The function that will calculate the return value. - - Return a calculated value which is evaluated lazily at the time of the invocation. - - The return value is calculated from the value of the actual method invocation arguments. - Notice how the arguments are retrieved by simply declaring them as part of the lambda - expression: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>(), - It.IsAny<int>())) - .Returns((string arg1, string arg2, int arg3) => arg1 + arg2 + arg3); - - - - - - Specifies a function that will calculate the value to return from the method, - retrieving the arguments for the invocation. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Type of the third argument of the invoked method. - Type of the fourth argument of the invoked method. - The function that will calculate the return value. - - Return a calculated value which is evaluated lazily at the time of the invocation. - - The return value is calculated from the value of the actual method invocation arguments. - Notice how the arguments are retrieved by simply declaring them as part of the lambda - expression: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>(), - It.IsAny<int>(), - It.IsAny<bool>())) - .Returns((string arg1, string arg2, int arg3, bool arg4) => arg1 + arg2 + arg3 + arg4); - - - - - - Defines the Throws verb. - - - - - Specifies the exception to throw when the method is invoked. - - Exception instance to throw. - - This example shows how to throw an exception when the method is - invoked with an empty string argument: - - mock.Expect(x => x.Execute("")) - .Throws(new ArgumentException()); - - - - - - Specifies the type of exception to throw when the method is invoked. - - Type of exception to instantiate and throw when the expectation is met. - - This example shows how to throw an exception when the method is - invoked with an empty string argument: - - mock.Expect(x => x.Execute("")) - .Throws<ArgumentException>(); - - - - - - Implements the fluent API. - - - - - Implements the fluent API. - - - - - Defines the Callback verb and overloads for callbacks on - expectations that return a value. - - Type of the return value of the expectation. - - - - Specifies a callback to invoke when the method is called. - - Callback method to invoke. - - The following example specifies a callback to set a boolean - value that can be used later: - - bool called = false; - mock.Expect(x => x.Execute()) - .Callback(() => called = true) - .Returns(true); - - Note that in the case of value-returning methods, after the Callback - call you can still specify the return value. - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation argument value. - - Notice how the specific string argument is retrieved by simply declaring - it as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute(It.IsAny<string>())) - .Callback((string command) => Console.WriteLine(command)) - .Returns(true); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation arguments values. - - Notice how the specific arguments are retrieved by simply declaring - them as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>())) - .Callback((string arg1, string arg2) => Console.WriteLine(arg1 + arg2)) - .Returns(true); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Type of the third argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation arguments values. - - Notice how the specific arguments are retrieved by simply declaring - them as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>(), - It.IsAny<int>())) - .Callback((string arg1, string arg2, int arg3) => Console.WriteLine(arg1 + arg2 + arg3)) - .Returns(true); - - - - - - Specifies a callback to invoke when the method is called that receives the original - arguments. - - Type of the first argument of the invoked method. - Type of the second argument of the invoked method. - Type of the third argument of the invoked method. - Type of the fourth argument of the invoked method. - Callback method to invoke. - - Invokes the given callback with the concrete invocation arguments values. - - Notice how the specific arguments are retrieved by simply declaring - them as part of the lambda expression for the callback: - - - mock.Expect(x => x.Execute( - It.IsAny<string>(), - It.IsAny<string>(), - It.IsAny<int>(), - It.IsAny<bool>())) - .Callback((string arg1, string arg2, int arg3, bool arg4) => Console.WriteLine(arg1 + arg2 + arg3 + arg4)) - .Returns(true); - - - - - - Implemented by all generated mock object instances. - - - - - Implemented by all generated mock object instances. - - - - - Reference the Mock that contains this as the mock.Object value. - - - - - Reference the Mock that contains this as the mock.Object value. - - - - - Implements the actual interception and method invocation for - all mocks. - - - - - Get an eventInfo for a given event name. Search type ancestors depth first if necessary. - - Name of the event, with the set_ or get_ prefix already removed - - - - Given a type return all of its ancestors, both types and interfaces. - - The type to find immediate ancestors of - - - - Implements the fluent API. - - - - - Defines the Never verb. - - - - - The expected invocation is never expected to happen. - - - - var mock = new Mock<ICommand>(); - mock.Expect(foo => foo.Execute("ping")) - .Never(); - - - - is always verified inmediately as - the invocations are performed, like strict mocks do - with unexpected invocations. - - - - - Implements the fluent API. - - - - - Implements the fluent API. - - - - - Implements the fluent API. - - - - - Defines the Callback verb for property setter expectations. - - - - Type of the property. - - - - Specifies a callback to invoke when the property is set that receives the - property value being set. - - Callback method to invoke. - - Invokes the given callback with the property value being set. - - mock.ExpectSet(x => x.Suspended) - .Callback((bool state) => Console.WriteLine(state)); - - - - - - Allows the specification of a matching condition for an - argument in a method invocation, rather than a specific - argument value. "It" refers to the argument being matched. - - - This class allows the expectation to match a method invocation - with an arbitrary value, with a value in a specified range, or - even one that matches a given predicate. - - - - - Matches any value of the given type. - - - Typically used when the actual argument value for a method - call is not relevant. - - - - // Throws an exception for a call to Remove with any string value. - mock.Expect(x => x.Remove(It.IsAny<string>())).Throws(new InvalidOperationException()); - - - Type of the value. - - - - Matches any value that satisfies the given predicate. - - Type of the argument to check. - The predicate used to match the method argument. - - Allows the specification of a predicate to perform matching - of method call arguments. - - - This example shows how to return the value 1 whenever the argument to the - Do method is an even number. - - mock.Expect(x => x.Do(It.Is<int>(i => i % 2 == 0))) - .Returns(1); - - This example shows how to throw an exception if the argument to the - method is a negative number: - - mock.Expect(x => x.GetUser(It.Is<int>(i => i < 0))) - .Throws(new ArgumentException()); - - - - - - Matches any value that is in the range specified. - - Type of the argument to check. - The lower bound of the range. - The upper bound of the range. - The kind of range. See . - - The following example shows how to expect a method call - with an integer argument within the 0..100 range. - - mock.Expect(x => x.HasInventory( - It.IsAny<string>(), - It.IsInRange(0, 100, Range.Inclusive))) - .Returns(false); - - - - - - Matches a string argument if it matches the given regular expression pattern. - - The pattern to use to match the string argument value. - - The following example shows how to expect a call to a method where the - string argument matches the given regular expression: - - mock.Expect(x => x.Check(It.IsRegex("[a-z]+"))).Returns(1); - - - - - - Matches a string argument if it matches the given regular expression pattern. - - The pattern to use to match the string argument value. - The options used to interpret the pattern. - - The following example shows how to expect a call to a method where the - string argument matches the given regular expression, in a case insensitive way: - - mock.Expect(x => x.Check(It.IsRegex("[a-z]+", RegexOptions.IgnoreCase))).Returns(1); - - - - - - Matcher to treat static functions as matchers. - - mock.Expect(x => x.StringMethod(A.MagicString())); - - pbulic static class A - { - [Matcher] - public static string MagicString() { return null; } - public static bool MagicString(string arg) - { - return arg == "magic"; - } - } - - Will success if: mock.Object.StringMethod("magic"); - and fail with any other call. - - - - - We need this non-generics base class so that - we can use from - generic code. - - - - - Base class for mocks and static helper class with methods that - apply to mocked objects, such as to - retrieve a from an object instance. - - - - - Base mock interface exposing non-generic members. - - - - - Creates a handler that can be associated to an event receiving - the given and can be used - to raise the event. - - Type of - data passed in to the event. - - This example shows how to invoke an event with a custom event arguments - class in a view that will cause its corresponding presenter to - react by changing its state: - - var mockView = new Mock<IOrdersView>(); - var mockedEvent = mockView.CreateEventHandler<OrderEventArgs>(); - - var presenter = new OrdersPresenter(mockView.Object); - - // Check that the presenter has no selection by default - Assert.Null(presenter.SelectedOrder); - - // Create a mock event handler of the appropriate type - var handler = mockView.CreateEventHandler<OrderEventArgs>(); - // Associate it with the event we want to raise - mockView.Object.Cancel += handler; - // Finally raise the event with a specific arguments data - handler.Raise(new OrderEventArgs { Order = new Order("moq", 500) }); - - // Now the presenter reacted to the event, and we have a selected order - Assert.NotNull(presenter.SelectedOrder); - Assert.Equal("moq", presenter.SelectedOrder.ProductName); - - - - - - Creates a handler that can be associated to an event receiving - a generic and can be used - to raise the event. - - - This example shows how to invoke a generic event in a view that will - cause its corresponding presenter to react by changing its state: - - var mockView = new Mock<IOrdersView>(); - var mockedEvent = mockView.CreateEventHandler(); - - var presenter = new OrdersPresenter(mockView.Object); - - // Check that the presenter is not in the "Canceled" state - Assert.False(presenter.IsCanceled); - - // Create a mock event handler of the appropriate type - var handler = mockView.CreateEventHandler(); - // Associate it with the event we want to raise - mockView.Object.Cancel += handler; - // Finally raise the event - handler.Raise(EventArgs.Empty); - - // Now the presenter reacted to the event, and changed its state - Assert.True(presenter.IsCanceled); - - - - - - Verifies that all verifiable expectations have been met. - - - This example sets up an expectation and marks it as verifiable. After - the mock is used, a call is issued on the mock - to ensure the method in the expectation was invoked: - - var mock = new Mock<IWarehouse>(); - mock.Expect(x => x.HasInventory(TALISKER, 50)).Verifiable().Returns(true); - ... - // other test code - ... - // Will throw if the test code has didn't call HasInventory. - mock.Verify(); - - - Not all verifiable expectations were met. - - - - Verifies all expectations regardless of whether they have - been flagged as verifiable. - - - This example sets up an expectation without marking it as verifiable. After - the mock is used, a call is issued on the mock - to ensure that all expectations are met: - - var mock = new Mock<IWarehouse>(); - mock.Expect(x => x.HasInventory(TALISKER, 50)).Returns(true); - ... - // other test code - ... - // Will throw if the test code has didn't call HasInventory, even - // that expectation was not marked as verifiable. - mock.VerifyAll(); - - - At least one expectation was not met. - - - - Whether the base member virtual implementation will be called - for mocked classes if no expectation is met. Defaults to . - - - - - Determines how to generate default values for loose mocks on - unexpected invocations. - - - - - The mocked object instance. - - - - - Retrieves the mock object for the given object instance. - - Type of the mock to retrieve. Can be omitted as it's inferred - from the object instance passed in as the instance. - The instance of the mocked object. - The mock associated with the mocked object. - The received instance - was not created by Moq. - - The following example shows how to add a new expectation to an object - instance which is not the original but rather - the object associated with it: - - // Typed instance, not the mock, is retrieved from some test API. - HttpContextBase context = GetMockContext(); - - // context.Request is the typed object from the "real" API - // so in order to add an expectation to it, we need to get - // the mock that "owns" it - Mock<HttpRequestBase> request = Mock.Get(context.Request); - mock.Expect(req => req.AppRelativeCurrentExecutionFilePath) - .Returns(tempUrl); - - - - - - Initializes the mock - - - - - Returns the mocked object value. - - - - - Implements . - - - - - Implements . - - - - - Gets the interceptor target for the given expression and root mock, - building the intermediate hierarchy of mock objects if necessary. - - - - - Implements . - - Type of event argument class. - - - - Implements - - - - - Base class for mocks and static helper class with methods that - apply to mocked objects, such as to - retrieve a from an object instance. - - - - - Exposes the list of extra interfaces implemented by the mock. - - - - - Implements . - - - - - Implements . - - - - - Implements . - - - - - Specifies the class that will determine the default - value to return when invocations are made that - have no expectations and need to return a default - value (for loose mocks). - - - - - The mocked object instance. Implements . - - - - - Retrieves the type of the mocked object, its generic type argument. - This is used in the auto-mocking of hierarchy access. - - - - - Represents a generic event that has been mocked and can - be rised. - - - - - Provided solely to allow the interceptor to determine when the attached - handler is coming from this mocked event so we can assign the - corresponding EventInfo for it. - - - - - Raises the associated event with the given - event argument data. - - - - - Provides support for attaching a to - a generic event. - - Event to convert. - - - - Event raised whenever the mocked event is rised. - - - - - Options to customize the behavior of the mock. - - - - - Causes the mock to always throw - an exception for invocations that don't have a - corresponding expectation. - - - - - Will never throw exceptions, returning default - values when necessary (null for reference types, - zero for value types or empty enumerables and arrays). - - - - - Default mock behavior, which equals . - - - - - Exception thrown by mocks when expectations are not met, - the mock is not properly setup, etc. - - - A distinct exception type is provided so that exceptions - thrown by the mock can be differentiated in tests that - expect other exceptions to be thrown (i.e. ArgumentException). - - Richer exception hierarchy/types are not provided as - tests typically should not catch or expect exceptions - from the mocks. These are typically the result of changes - in the tested class or its collaborators implementation, and - result in fixes in the mock setup so that they dissapear and - allow the test to pass. - - - - - - Supports the serialization infrastructure. - - Serialization information. - Streaming context. - - - - Supports the serialization infrastructure. - - Serialization information. - Streaming context. - - - - Made internal as it's of no use for - consumers, but it's important for - our own tests. - - - - - Used by the mock factory to accumulate verification - failures. - - - - - Supports the serialization infrastructure. - - - - - Utility factory class to use to construct multiple - mocks when consistent verification is - desired for all of them. - - - If multiple mocks will be created during a test, passing - the desired (if different than the - or the one - passed to the factory constructor) and later verifying each - mock can become repetitive and tedious. - - This factory class helps in that scenario by providing a - simplified creation of multiple mocks with a default - (unless overriden by calling - ) and posterior verification. - - - - The following is a straightforward example on how to - create and automatically verify strict mocks using a : - - var factory = new MockFactory(MockBehavior.Strict); - - var foo = factory.Create<IFoo>(); - var bar = factory.Create<IBar>(); - - // no need to call Verifiable() on the expectation - // as we'll be validating all expectations anyway. - foo.Expect(f => f.Do()); - bar.Expect(b => b.Redo()); - - // exercise the mocks here - - factory.VerifyAll(); - // At this point all expectations are already checked - // and an optional MockException might be thrown. - // Note also that because the mocks are strict, any invocation - // that doesn't have a matching expectation will also throw a MockException. - - The following examples shows how to setup the factory - to create loose mocks and later verify only verifiable expectations: - - var factory = new MockFactory(MockBehavior.Loose); - - var foo = factory.Create<IFoo>(); - var bar = factory.Create<IBar>(); - - // this expectation will be verified at the end of the "using" block - foo.Expect(f => f.Do()).Verifiable(); - - // this expectation will NOT be verified - foo.Expect(f => f.Calculate()); - - // this expectation will be verified at the end of the "using" block - bar.Expect(b => b.Redo()).Verifiable(); - - // exercise the mocks here - // note that because the mocks are Loose, members - // called in the interfaces for which no matching - // expectations exist will NOT throw exceptions, - // and will rather return default values. - - factory.Verify(); - // At this point verifiable expectations are already checked - // and an optional MockException might be thrown. - - The following examples shows how to setup the factory with a - default strict behavior, overriding that default for a - specific mock: - - var factory = new MockFactory(MockBehavior.Strict); - - // this particular one we want loose - var foo = factory.Create<IFoo>(MockBehavior.Loose); - var bar = factory.Create<IBar>(); - - // set expectations - - // exercise the mocks here - - factory.Verify(); - - - - - - - Initializes the factory with the given - for newly created mocks from the factory. - - The behavior to use for mocks created - using the factory method if not overriden - by using the overload. - - - - Creates a new mock with the default - specified at factory construction time. - - Type to mock. - A new . - - - var factory = new MockFactory(MockBehavior.Strict); - - var foo = factory.Create<IFoo>(); - // use mock on tests - - factory.VerifyAll(); - - - - - - Creates a new mock with the default - specified at factory construction time and with the - the given constructor arguments for the class. - - - The mock will try to find the best match constructor given the - constructor arguments, and invoke that to initialize the instance. - This applies only to classes, not interfaces. - - Type to mock. - Constructor arguments for mocked classes. - A new . - - - var factory = new MockFactory(MockBehavior.Default); - - var mock = factory.Create<MyBase>("Foo", 25, true); - // use mock on tests - - factory.Verify(); - - - - - - Creates a new mock with the given . - - Type to mock. - Behavior to use for the mock, which overrides - the default behavior specified at factory construction time. - A new . - - The following example shows how to create a mock with a different - behavior to that specified as the default for the factory: - - var factory = new MockFactory(MockBehavior.Strict); - - var foo = factory.Create<IFoo>(MockBehavior.Loose); - - - - - - Creates a new mock with the given - and with the the given constructor arguments for the class. - - - The mock will try to find the best match constructor given the - constructor arguments, and invoke that to initialize the instance. - This applies only to classes, not interfaces. - - Type to mock. - Behavior to use for the mock, which overrides - the default behavior specified at factory construction time. - Constructor arguments for mocked classes. - A new . - - The following example shows how to create a mock with a different - behavior to that specified as the default for the factory, passing - constructor arguments: - - var factory = new MockFactory(MockBehavior.Default); - - var mock = factory.Create<MyBase>(MockBehavior.Strict, "Foo", 25, true); - - - - - - Implements creation of a new mock within the factory. - - Type to mock. - The behavior for the new mock. - Optional arguments for the construction of the mock. - - - - Verifies all verifiable expectations on all mocks created - by this factory. - - - One or more mocks had expectations that were not satisfied. - - - - Verifies all verifiable expectations on all mocks created - by this factory. - - - One or more mocks had expectations that were not satisfied. - - - - Invokes for each mock - in , and accumulates the resulting - that might be - thrown from the action. - - The action to execute against - each mock. - - - - Whether the base member virtual implementation will be called - for mocked classes if no expectation is met. Defaults to . - - - - - Specifies the behavior to use when returning default values for - unexpected invocations on loose mocks. - - - - - Gets the mocks that have been created by this factory and - that will get verified together. - - - - - A strongly-typed resource class, for looking up localized strings, etc. - - - - - Returns the cached ResourceManager instance used by this class. - - - - - Overrides the current thread's CurrentUICulture property for all - resource lookups using this strongly typed resource class. - - - - - Looks up a localized string similar to Mock type has already been initialized by accessing its Object property. Adding interfaces must be done before that.. - - - - - Looks up a localized string similar to Can only add interfaces to the mock.. - - - - - Looks up a localized string similar to Can't set return value for void method {0}.. - - - - - Looks up a localized string similar to Constructor arguments cannot be passed for interface mocks.. - - - - - Looks up a localized string similar to A matching constructor for the given arguments was not found on the mocked type.. - - - - - Looks up a localized string similar to Invalid expectation on a non-overridable member: - {0}. - - - - - Looks up a localized string similar to A lambda expression is expected as the argument to It.Is<T>.. - - - - - Looks up a localized string similar to Invocation {0} should not have been made.. - - - - - Looks up a localized string similar to Expression is not a method invocation: {0}. - - - - - Looks up a localized string similar to Expression is not a property access: {0}. - - - - - Looks up a localized string similar to Expression {0} involves a field access, which is not supported. Use properties instead.. - - - - - Looks up a localized string similar to Type to mock must be an interface or an abstract or non-sealed class. . - - - - - Looks up a localized string similar to Cannot retrieve a mock with the given object type {0} as it's not the main type of the mock or any of its additional interfaces. - Please cast the argument to one of the supported types: {1}. - Remember that there's no generics covariance in the CLR, so your object must be one of these types in order for the call to succeed.. - - - - - Looks up a localized string similar to Member {0}.{1} does not exist.. - - - - - Looks up a localized string similar to Method {0}.{1} is public. Use strong-typed Expect overload instead: - mock.Expect(x => x.{1}()); - . - - - - - Looks up a localized string similar to {0} invocation failed with mock behavior {1}. - {2}. - - - - - Looks up a localized string similar to Expected only {0} calls to {1}.. - - - - - Looks up a localized string similar to Expected only one call to {0}.. - - - - - Looks up a localized string similar to All invocations on the mock must have a corresponding expectation.. - - - - - Looks up a localized string similar to The given invocation was not performed on the mock.. - - - - - Looks up a localized string similar to Object instance was not created by Moq.. - - - - - Looks up a localized string similar to Property {0}.{1} does not exist.. - - - - - Looks up a localized string similar to Property {0}.{1} is write-only.. - - - - - Looks up a localized string similar to Property {0}.{1} is read-only.. - - - - - Looks up a localized string similar to Cannot raise a mocked event unless it has been associated (attached) to a concrete event in a mocked object.. - - - - - Looks up a localized string similar to Invocation needs to return a value and therefore must have a corresponding expectation that provides it.. - - - - - Looks up a localized string similar to To set expectations for public property {0}.{1}, use the typed overloads, such as: - mock.Expect(x => x.{1}).Returns(value); - mock.ExpectGet(x => x.{1}).Returns(value); //equivalent to previous one - mock.ExpectSet(x => x.{1}).Callback(callbackDelegate); - . - - - - - Looks up a localized string similar to Expression {0} is not supported.. - - - - - Looks up a localized string similar to Only property accesses are supported in intermediate invocations on an expectation. Unsupported expression {0}.. - - - - - Looks up a localized string similar to Expression contains intermediate property access {0}.{1} which is of type {2} and cannot be mocked. Unsupported expression {3}.. - - - - - Looks up a localized string similar to Member {0} is not supported for protected mocking.. - - - - - Looks up a localized string similar to To set expectations for protected property {0}.{1}, use: - mock.Expect<{2}>(x => x.{1}).Returns(value); - mock.ExpectGet(x => x.{1}).Returns(value); //equivalent to previous one - mock.ExpectSet(x => x.{1}).Callback(callbackDelegate);. - - - - - Looks up a localized string similar to The following expectations were not met: - {0}. - - - - - Allows expectations to be set for protected members by using their - name as a string, rather than strong-typing them which is not possible - due to their visibility. - - - - - Sets an expectation on the void method with the given - , optionally specifying - arguments for the method call. - - Name of the void method to be invoke. - Optional arguments for the invocation. - - - - Sets an expectation on a property or a non void method with the given - , optionally specifying - arguments for the method call. - - Name of the method or property to be invoke. - Optional arguments for the invocation. - Return type of the method or property. - - - - Sets an expectation on a property getter with the given - . - - Name of the property. - Type of the property. - - - - Sets an expectation on a property setter with the given - . - - Name of the property. - Type of the property. - - - - Allows the specification of a matching condition for an - argument in a protected member expectation, rather than a specific - argument value. "ItExpr" refers to the argument being matched. - - - Use this variant of argument matching instead of - for protected expectations. - This class allows the expectation to match a method invocation - with an arbitrary value, with a value in a specified range, or - even one that matches a given predicate. - - - - - Matches any value of the given type. - - - Typically used when the actual argument value for a method - call is not relevant. - - - - // Throws an exception for a call to Remove with any string value. - mock.Protected() - .Expect("Remove", ItExpr.IsAny<string>()) - .Throws(new InvalidOperationException()); - - - Type of the value. - - - - Matches any value that satisfies the given predicate. - - Type of the argument to check. - The predicate used to match the method argument. - - Allows the specification of a predicate to perform matching - of method call arguments. - - - This example shows how to return the value 1 whenever the argument to the - Do method is an even number. - - mock.Protected() - .Expect("Do", ItExpr.Is<int>(i => i % 2 == 0)) - .Returns(1); - - This example shows how to throw an exception if the argument to the - method is a negative number: - - mock.Protected() - .Expect("GetUser", ItExpr.Is<int>(i => i < 0)) - .Throws(new ArgumentException()); - - - - - - Matches any value that is in the range specified. - - Type of the argument to check. - The lower bound of the range. - The upper bound of the range. - The kind of range. See . - - The following example shows how to expect a method call - with an integer argument within the 0..100 range. - - mock.Protected() - .Expect("HasInventory", - ItExpr.IsAny<string>(), - ItExpr.IsInRange(0, 100, Range.Inclusive)) - .Returns(false); - - - - - - Matches a string argument if it matches the given regular expression pattern. - - The pattern to use to match the string argument value. - - The following example shows how to expect a call to a method where the - string argument matches the given regular expression: - - mock.Protected() - .Expect("Check", ItExpr.IsRegex("[a-z]+")) - .Returns(1); - - - - - - Matches a string argument if it matches the given regular expression pattern. - - The pattern to use to match the string argument value. - The options used to interpret the pattern. - - The following example shows how to expect a call to a method where the - string argument matches the given regular expression, in a case insensitive way: - - mock.Protected() - .Expect("Check", ItExpr.IsRegex("[a-z]+", RegexOptions.IgnoreCase)) - .Returns(1); - - - - - - Enables the Protected() method on , - allowing expectations to be set for protected members by using their - name as a string, rather than strong-typing them which is not possible - due to their visibility. - - - - - Enable protected expectations for the mock. - - Mocked object type. Typically omitted as it can be inferred from the mock instance. - The mock to set the protected expectations on. - - - - - - - - - - - - Kind of range to use in a filter specified through - . - - - - - The range includes the to and - from values. - - - - - The range does not include the to and - from values. - - - - - Determines the way default values are generated - calculated for loose mocks. - - - - - Default behavior, which generates empty values for - value types (i.e. default(int)), empty array and - enumerables, and nulls for all other reference types. - - - - - Whenever the default value generated by - is null, replaces this value with a mock (if the type - can be mocked). - - - For sealed classes, a null value will be generated. - - - - - Core implementation of the interface. - - - Type to mock. - - - - Initializes an instance of the mock with default behavior and with - the given constructor arguments for the class. (Only valid when is a class) - - - The mock will try to find the best match constructor given the constructor arguments, and invoke that - to initialize the instance. This applies only for classes, not interfaces. - - - var mock = new Mock<MyProvider>(someArgument, 25); - - Optional constructor arguments if the mocked type is a class. - - - - Initializes an instance of the mock with default behavior. - - - var mock = new Mock<IFormatProvider>(); - - - - - Initializes an instance of the mock with the specified behavior. - - - var mock = new Mock<IFormatProvider>(MockBehavior.Relaxed); - - Behavior of the mock. - - - - Initializes an instance of the mock with a specific behavior with - the given constructor arguments for the class. - - - The mock will try to find the best match constructor given the constructor arguments, and invoke that - to initialize the instance. This applies only to classes, not interfaces. - - - var mock = new Mock<MyProvider>(someArgument, 25); - - Behavior of the mock. - Optional constructor arguments if the mocked type is a class. - - - - Returns the mocked object value. - - - - - Implements . - - Lambda expression that specifies the expected method invocation. - - - - Implements . - - Type of the return value. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected method invocation. - - - - Implements . - - Type of the property. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected property getter. - - - - Implements . - - Type of the property. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected property setter. - - - - Implements . - - Type of the property. Typically omitted as it can be inferred from the expression. - Lambda expression that specifies the expected property setter. - The value expected to be set for the property. - - - - Implements . - - Expression to verify. - - - - Implements . - - Expression to verify. - Type of return value from the expression. - - - - Implements . - - Expression to verify. - Type of the property to verify. Typically omitted as it can - be inferred from the expression's return type. - - - - Implements . - - Expression to verify. - Type of the property to verify. Typically omitted as it can - be inferred from the expression's return type. - - - - Implements . - - Expression to verify. - The value that should have been set on the property. - Type of the property to verify. Typically omitted as it can - be inferred from the expression's return type. - - - - Implements . - - - - - Implements . - - - - - Implements . - - Type of interface to cast the mock to. - - - - Exposes the mocked object instance. - - - - - A that returns an empty default value - for non-mockeable types, and mocks for all other types (interfaces and - non-sealed classes) that can be mocked. - - - - - Provides a typed for a - specific type of . - - The type of event arguments required by the event. - - The mocked event can either be a or custom - event handler which follows .NET practice of providing object sender, EventArgs args - kind of signature. - - - - - Raises the associated event with the given - event argument data. - - Data to pass to the event. - - - - Provides support for attaching a to - a generic event. - - Event to convert. - - - - Provided solely to allow the interceptor to determine when the attached - handler is coming from this mocked event so we can assign the - corresponding EventInfo for it. - - - - - Adds Stub extension method to a mock so that you can - stub properties. - - - - - Specifies that the given property should have stub behavior, - meaning that setting its value will cause it to be saved and - later returned when the property is requested. - - Mocked type, inferred from the object - where this method is being applied (does not need to be specified). - Type of the property, inferred from the property - expression (does not need to be specified). - The instance to stub. - Property expression to stub. - - If you have an interface with an int property Value, you might - stub it using the following straightforward call: - - var mock = new Mock<IHaveValue>(); - mock.Stub(v => v.Value); - - After the Stub call has been issued, setting and - retrieving the object value will behave as expected: - - IHaveValue v = mock.Object; - - v.Value = 5; - Assert.Equal(5, v.Value); - - - - - - Specifies that the given property should have stub behavior, - meaning that setting its value will cause it to be saved and - later returned when the property is requested. This overload - allows setting the initial value for the property. - - Mocked type, inferred from the object - where this method is being applied (does not need to be specified). - Type of the property, inferred from the property - expression (does not need to be specified). - The instance to stub. - Property expression to stub. - Initial value for the property. - - If you have an interface with an int property Value, you might - stub it using the following straightforward call: - - var mock = new Mock<IHaveValue>(); - mock.Stub(v => v.Value, 5); - - After the Stub call has been issued, setting and - retrieving the object value will behave as expected: - - IHaveValue v = mock.Object; - // Initial value was stored - Assert.Equal(5, v.Value); - - // New value set which changes the initial value - v.Value = 6; - Assert.Equal(6, v.Value); - - - - - - Stubs all properties on the mock, setting the default value to - the one generated as specified by the - property. - - Mocked type, typically omitted as it can be inferred from the mock argument. - The mock to stub. - - If the mock is set to , - the mocked default values will also be stubbed recursively. - - - - diff --git a/lib/tests/ServiceStack.Common.Tests.dll b/lib/tests/ServiceStack.Common.Tests.dll deleted file mode 100644 index 5d74477e..00000000 Binary files a/lib/tests/ServiceStack.Common.Tests.dll and /dev/null differ diff --git a/lib/tests/nunit.framework.dll b/lib/tests/nunit.framework.dll deleted file mode 100644 index 2729ddf2..00000000 Binary files a/lib/tests/nunit.framework.dll and /dev/null differ diff --git a/lib/tests/nunit.framework.xml b/lib/tests/nunit.framework.xml deleted file mode 100644 index 911ebf8b..00000000 --- a/lib/tests/nunit.framework.xml +++ /dev/null @@ -1,5622 +0,0 @@ - - - - nunit.framework - - - - - EmptyStringConstraint tests whether a string is empty. - - - - - EmptyConstraint tests a whether a string or collection is empty, - postponing the decision about which test is applied until the - type of the actual argument is known. - - - - - The Constraint class is the base of all built-in or - user-defined constraints in NUnit. It provides the operator - overloads used to combine constraints. - - - - - Static UnsetObject used to detect derived constraints - failing to set the actual value. - - - - - If true, all string comparisons will ignore case - - - - - If true, strings in error messages will be clipped - - - - - If true, arrays will be treated as collections, allowing - those of different dimensions to be compared - - - - - If non-zero, equality comparisons within the specified - tolerance will succeed. - - - - - IComparer object used in comparisons for some constraints. - - - - - The actual value being tested against a constraint - - - - - Flag the constraint to use a tolerance when determining equality. - Currently only used for doubles and floats. - - Tolerance to be used - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Write the failure message to the MessageWriter provided - as an argument. The default implementation simply passes - the constraint and the actual value to the writer, which - then displays the constraint description and the value. - - Constraints that need to provide additional details, - such as where the error occured can override this. - - The MessageWriter on which to display the message - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if the - argument constraint is not satisfied. - - - - - Flag the constraint to ignore case and return self. - - - - - Flag the constraint to suppress string clipping - and return self. - - - - - Flag the constraint to compare arrays as collections - and return self. - - - - - Class used to detect any derived constraints - that fail to set the actual value in their - Matches override. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SubstringConstraint can test whether a string contains - the expected substring. - - - - - Initializes a new instance of the class. - - The expected. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - StartsWithConstraint can test whether a string starts - with an expected substring. - - - - - Initializes a new instance of the class. - - The expected string - - - - Test whether the constraint is matched by the actual value. - This is a template method, which calls the IsMatch method - of the derived class. - - - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EndsWithConstraint can test whether a string ends - with an expected substring. - - - - - Initializes a new instance of the class. - - The expected string - - - - Test whether the constraint is matched by the actual value. - This is a template method, which calls the IsMatch method - of the derived class. - - - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - RegexConstraint can test whether a string matches - the pattern provided. - - - - - Initializes a new instance of the class. - - The pattern. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - ConstraintBuilder is used to resolve the Not and All properties, - which serve as prefix operators for constraints. With the addition - of an operand stack, And and Or could be supported, but we have - left them out in favor of a simpler, more type-safe implementation. - Use the & and | operator overloads to combine constraints. - - - - - Implicitly convert ConstraintBuilder to an actual Constraint - at the point where the syntax demands it. - - - - - - - Resolves the chain of constraints using an - EqualConstraint as base. - - - - - Resolves the chain of constraints using a - SameAsConstraint as base. - - - - - Resolves the chain of constraints using a - LessThanConstraint as base. - - - - - Resolves the chain of constraints using a - GreaterThanConstraint as base. - - - - - Resolves the chain of constraints using a - LessThanOrEqualConstraint as base. - - - - - Resolves the chain of constraints using a - LessThanOrEqualConstraint as base. - - - - - Resolves the chain of constraints using a - GreaterThanOrEqualConstraint as base. - - - - - Resolves the chain of constraints using a - GreaterThanOrEqualConstraint as base. - - - - - Resolves the chain of constraints using an - ExactTypeConstraint as base. - - - - - Resolves the chain of constraints using an - InstanceOfTypeConstraint as base. - - - - - Resolves the chain of constraints using an - AssignableFromConstraint as base. - - - - - Resolves the chain of constraints using a - ContainsConstraint as base. This constraint - will, in turn, make use of the appropriate - second-level constraint, depending on the - type of the actual argument. - - - - - Resolves the chain of constraints using a - CollectionContainsConstraint as base. - - The expected object - - - - Resolves the chain of constraints using a - StartsWithConstraint as base. - - - - - Resolves the chain of constraints using a - StringEndingConstraint as base. - - - - - Resolves the chain of constraints using a - StringMatchingConstraint as base. - - - - - Resolves the chain of constraints using a - CollectionEquivalentConstraint as base. - - - - - Resolves the chain of constraints using a - CollectionContainingConstraint as base. - - - - - Resolves the chain of constraints using a - CollectionSubsetConstraint as base. - - - - - Resolves the chain of constraints using a - PropertyConstraint as base - - - - - Resolves the chain of constraints using a - PropertyCOnstraint on Length as base - - - - - - - Resolves the chain of constraints using a - PropertyCOnstraint on Length as base - - - - - - - Modifies the ConstraintBuilder by pushing a Prop operator on the - ops stack and the name of the property on the opnds stack. - - - - - - - Resolve a constraint that has been recognized by applying - any pending operators and returning the resulting Constraint. - - A constraint that incorporates all pending operators - - - - Resolves the chain of constraints using - EqualConstraint(null) as base. - - - - - Resolves the chain of constraints using - EqualConstraint(true) as base. - - - - - Resolves the chain of constraints using - EqualConstraint(false) as base. - - - - - Resolves the chain of constraints using - Is.NaN as base. - - - - - Resolves the chain of constraints using - Is.Empty as base. - - - - - Resolves the chain of constraints using - Is.Unique as base. - - - - - Modifies the ConstraintBuilder by pushing a Not operator on the stack. - - - - - Modifies the ConstraintBuilder by pushing a Not operator on the stack. - - - - - Modifies the ConstraintBuilder by pushing an All operator on the stack. - - - - - Modifies the ConstraintBuilder by pushing a Some operator on the stack. - - - - - Modifies the constraint builder by pushing All and Not operators on the stack - - - - - CollectionConstraint is the abstract base class for - constraints that operate on collections. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Protected method to be implemented by derived classes - - - - - - - CollectionTally counts (tallies) the number of - occurences of each object in one or more enuerations. - - - - - Construct a CollectionTally object from a collection - - - - - - Remove the counts for a collection from the tally, - so long as their are sufficient items to remove. - The tallies are not permitted to become negative. - - The collection to remove - True if there were enough items to remove, otherwise false - - - - Test whether all the counts are equal to a given value - - The value to be looked for - True if all counts are equal to the value, otherwise false - - - - Get the count of the number of times an object is present in the tally - - - - - EmptyCollectionConstraint tests whether a colletion is empty. - - - - - Check that the collection is empty - - - - - - - Write the constraint description to a MessageWriter - - - - - - UniqueItemsConstraint tests whether all the items in a - collection are unique. - - - - - Check that all items are unique. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - CollectionContainsConstraint is used to test whether a collection - contains an expected object as a member. - - - - - Construct a CollectionContainsConstraint - - - - - - Test whether the expected item is contained in the collection - - - - - - - Write a descripton of the constraint to a MessageWriter - - - - - - CollectionEquivalentCOnstraint is used to determine whether two - collections are equivalent. - - - - - Construct a CollectionEquivalentConstraint - - - - - - Test whether two collections are equivalent - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - CollectionSubsetConstraint is used to determine whether - one collection is a subset of another - - - - - Construct a CollectionSubsetConstraint - - The collection that the actual value is expected to be a subset of - - - - Test whether the actual collection is a subset of - the expected collection provided. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - EqualConstraint is able to compare an actual value with the - expected value provided in its constructor. - - - - - Initializes a new instance of the class. - - The expected value. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write a failure message. Overridden to provide custom - failure messages for EqualConstraint. - - The MessageWriter to write to - - - - Write description of this constraint - - The MessageWriter to write to - - - - Helper method to compare two arrays - - - - - Method to compare two DirectoryInfo objects - - first directory to compare - second directory to compare - true if equivalent, false if not - - - - Display the failure information for two collections that did not match. - - The MessageWriter on which to display - The expected collection. - The actual collection - The depth of this failure in a set of nested collections - - - - Displays a single line showing the types and sizes of the expected - and actual collections or arrays. If both are identical, the value is - only shown once. - - The MessageWriter on which to display - The expected collection or array - The actual collection or array - The indentation level for the message line - - - - Displays a single line showing the point in the expected and actual - arrays at which the comparison failed. If the arrays have different - structures or dimensions, both values are shown. - - The MessageWriter on which to display - The expected array - The actual array - Index of the failure point in the underlying collections - The indentation level for the message line - - - - Abstract base class used for prefixes - - - - - The base constraint - - - - - Construct given a base constraint - - - - - - Set all modifiers applied to the prefix into - the base constraint before matching - - - - - NotConstraint negates the effect of some other constraint - - - - - Initializes a new instance of the class. - - The base constraint to be negated. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for if the base constraint fails, false if it succeeds - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a MessageWriter. - - The writer on which the actual value is displayed - - - - AllItemsConstraint applies another constraint to each - item in a collection, succeeding if they all succeed. - - - - - Construct an AllItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - SomeItemsConstraint applies another constraint to each - item in a collection, succeeding if any of them succeeds. - - - - - Construct a SomeItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - SomeItemsConstraint applies another constraint to each - item in a collection, succeeding if any of them succeeds. - - - - - Construct a SomeItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - SameAsConstraint tests whether an object is identical to - the object passed to its constructor - - - - - Initializes a new instance of the class. - - The expected object. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - TypeConstraint is the abstract base for constraints - that take a Type as their expected value. - - - - - The expected Type used by the constraint - - - - - Construct a TypeConstraint for a given Type - - - - - - Write the actual value for a failing constraint test to a - MessageWriter. TypeCOnstraints override this method to write - the name of the type. - - The writer on which the actual value is displayed - - - - ExactTypeConstraint is used to test that an object - is of the exact type provided in the constructor - - - - - Construct an ExactTypeConstraint for a given Type - - - - - - Test that an object is of the exact type specified - - - - - - - Write the description of this constraint to a MessageWriter - - - - - - InstanceOfTypeConstraint is used to test that an object - is of the same type provided or derived from it. - - - - - Construct an InstanceOfTypeConstraint for the type provided - - - - - - Test whether an object is of the specified type or a derived type - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - AssignableFromConstraint is used to test that an object - can be assigned from a given Type. - - - - - Construct an AssignableFromConstraint for the type provided - - - - - - Test whether an object can be assigned from the specified type - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - Abstract base class for constraints that compare values to - determine if one is greater than, equal to or less than - the other. - - - - - The value against which a comparison is to be made - - - - - If true, less than returns success - - - - - if true, equal returns success - - - - - if true, greater than returns success - - - - - The predicate used as a part of the description - - - - - Initializes a new instance of the class. - - The value against which to make a comparison. - if set to true less succeeds. - if set to true equal succeeds. - if set to true greater succeeds. - String used in describing the constraint. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Tests whether a value is greater than the value supplied to its constructor - - - - - Initializes a new instance of the class. - - The expected value. - - - - Tests whether a value is greater than or equal to the value supplied to its constructor - - - - - Initializes a new instance of the class. - - The expected value. - - - - Tests whether a value is less than the value supplied to its constructor - - - - - Initializes a new instance of the class. - - The expected value. - - - - Tests whether a value is less than or equal to the value supplied to its constructor - - - - - Initializes a new instance of the class. - - The expected value. - - - - The Numerics class contains common operations on numeric values. - - - - - Checks the type of the object, returning true if - the object is a numeric type. - - The object to check - true if the object is a numeric type - - - - Checks the type of the object, returning true if - the object is a floating point numeric type. - - The object to check - true if the object is a floating point numeric type - - - - Checks the type of the object, returning true if - the object is a fixed point numeric type. - - The object to check - true if the object is a fixed point numeric type - - - - Test two numeric values for equality, performing the usual numeric - conversions and using a provided or default tolerance. If the value - referred to by tolerance is null, this method may set it to a default. - - The expected value - The actual value - A reference to the numeric tolerance in effect - True if the values are equal - - - - Compare two numeric values, performing the usual numeric conversions. - - The expected value - The actual value - - - - - ContainsConstraint tests a whether a string contains a substring - or a collection contains an object. It postpones the decision of - which test to use until the type of the actual argument is known. - This allows testing whether a string is contained in a collection - or as a substring of another string using the same syntax. - - - - - Initializes a new instance of the class. - - The expected. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Summary description for PropertyConstraint. - - - - - Initializes a new instance of the class. - - The name. - The constraint to apply to the property. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - BinaryOperation is the abstract base of all constraints - that combine two other constraints in some fashion. - - - - - The first constraint being combined - - - - - The second constraint being combined - - - - - Construct a BinaryOperation from two other constraints - - The first constraint - The second constraint - - - - AndConstraint succeeds only if both members succeed. - - - - - Create an AndConstraint from two other constraints - - The first constraint - The second constraint - - - - Apply both member constraints to an actual value, succeeding - succeeding only if both of them succeed. - - The actual value - True if the constraints both succeeded - - - - Write a description for this contraint to a MessageWriter - - The MessageWriter to receive the description - - - - OrConstraint succeeds if either member succeeds - - - - - Create an OrConstraint from two other constraints - - The first constraint - The second constraint - - - - Apply the member constraints to an actual value, succeeding - succeeding as soon as one of them succeeds. - - The actual value - True if either constraint succeeded - - - - Write a description for this contraint to a MessageWriter - - The MessageWriter to receive the description - - - - The Is class is a helper class with properties and methods - that supply a number of constraints used in Asserts. - - - - - Is.Null returns a static constraint that tests for null - - - - - Is.True returns a static constraint that tests whether a value is true - - - - - Is.False returns a static constraint that tests whether a value is false - - - - - Is.NaN returns a static constraint that tests whether a value is an NaN - - - - - Is.Empty returns a static constraint that tests whether a string or collection is empty - - - - - Is.Unique returns a static constraint that tests whether a collection contains all unque items. - - - - - Is.EqualTo returns a constraint that tests whether the - actual value equals the supplied argument - - - - - - - Is.SameAs returns a constraint that tests whether the - actual value is the same object as the supplied argument. - - - - - - - Is.GreaterThan returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Is.GreaterThanOrEqualTo returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Is.AtLeast is a synonym for Is.GreaterThanOrEqualTo - - - - - Is.LessThan returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Is.LessThanOrEqualTo returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Is.AtMost is a synonym for Is.LessThanOrEqualTo - - - - - Is.TypeOf returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Is.InstanceOfType returns a constraint that tests whether - the actual value is of the type supplied as an argument - or a derived type. - - - - - Is.AssignableFrom returns a constraint that tests whether - the actual value is assignable from the type supplied as - an argument. - - - - - - - Is.EquivalentTo returns a constraint that tests whether - the actual value is a collection containing the same - elements as the collection supplied as an arument - - - - - Is.SubsetOf returns a constraint that tests whether - the actual value is a subset of the collection - supplied as an arument - - - - - Is.Not returns a ConstraintBuilder that negates - the constraint that follows it. - - - - - Is.All returns a ConstraintBuilder, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. This property is - a synonym for Has.AllItems. - - - - - The Iz class is a synonym for Is intended for use in VB, - which regards Is as a keyword. - - - - - The Text class is a helper class with properties and methods - that supply a number of constraints used with strings. - - - - - Contains returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - DoesNotContain returns a constraint that fails if the actual - value contains the substring supplied as an argument. - - - - - StartsWith returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - DoesNotStartWith returns a constraint that fails if the actual - value starts with the substring supplied as an argument. - - - - - EndsWith returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - DoesNotEndWith returns a constraint that fails if the actual - value ends with the substring supplied as an argument. - - - - - Matches returns a constraint that succeeds if the actual - value matches the pattern supplied as an argument. - - - - - - - DoesNotMatch returns a constraint that failss if the actual - value matches the pattern supplied as an argument. - - - - - - - Text.All returns a ConstraintBuilder, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - The List class is a helper class with properties and methods - that supply a number of constraints used with lists and collections. - - - - - List.Map returns a ListMapper, which can be used to map - the original collection to another collection. - - - - - - - ListMapper is used to transform a collection used as an actual argument - producing another collection to be used in the assertion. - - - - - Construct a ListMapper based on a collection - - The collection to be transformed - - - - Produces a collection containing all the values of a property - - The collection of property values - - - - - Summary description for HasNoPrefixB. - - - - - Returns a new ConstraintBuilder, which will apply the - following constraint to a named property of the object - being tested. - - The name of the property - - - - Returns a new PropertyConstraint checking for the - existence of a particular property value. - - The name of the property to look for - The expected value of the property - - - - Returns a new PropertyConstraint for the Length property - - - - - - - Returns a new PropertyConstraint or the Count property - - - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - The expected object - - - - Has.No returns a ConstraintBuilder that negates - the constraint that follows it. - - - - - Has.AllItems returns a ConstraintBuilder, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Has.Some returns a ConstraintBuilder, which will apply - the following constraint to all members of a collection, - succeeding if any of them succeed. It is a synonym - for Has.Item. - - - - - Has.None returns a ConstraintBuilder, which will apply - the following constraint to all members of a collection, - succeeding only if none of them succeed. - - - - - Nested class that allows us to restrict the number - of key words that may appear after Has.No. - - - - - Return a ConstraintBuilder conditioned to apply - the following constraint to a property. - - The property name - A ConstraintBuilder - - - - Return a Constraint that succeeds if the expected object is - not contained in a collection. - - The expected object - A Constraint - - - - The Assert class contains a collection of static methods that - implement the most common assertions used in NUnit. - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display if the condition is true - Arguments to be used in formatting the message - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display if the condition is true - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to be displayed when the object is null - Arguments to be used in formatting the message - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to be displayed when the object is null - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to be displayed when the object is not null - Arguments to be used in formatting the message - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to be displayed when the object is not null - - - - Verifies that the object that is passed in is equal to null - If the object is not null null then an - is thrown. - - The object that is to be tested - - - - Verifies that the double is passed is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to be displayed when the object is not null - Arguments to be used in formatting the message - - - - Verifies that the double is passed is an NaN value. - If the object is not NaN then an - is thrown. - - The object that is to be tested - The message to be displayed when the object is not null - - - - Verifies that the double is passed is an NaN value. - If the object is not NaN then an - is thrown. - - The object that is to be tested - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that a string is empty - that is equal to string.Emtpy - - The string to be tested - The message to be displayed on failure - - - - Assert that a string is empty - that is equal to string.Emtpy - - The string to be tested - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing ICollection - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that a string is empty - that is equal to string.Emtpy - - The string to be tested - The message to be displayed on failure - - - - Assert that a string is empty - that is equal to string.Emtpy - - The string to be tested - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing ICollection - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The messge to display in case of failure - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The messge to display in case of failure - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - A message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - A message to display in case of failure - An array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - A message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - A message to display in case of failure - An array of objects to be used in formatting the message - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two uints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that two uints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - - - - Verifies that two uints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two ulongs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that two ulongs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - - - - Verifies that two ulongs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that two decimal are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message that will be displayed on failure - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equals then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equals then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message that will be displayed on failure - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equals then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - Verifies that two floats are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equals then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message displayed upon failure - Arguments to be used in formatting the message - - - - Verifies that two floats are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equals then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message displayed upon failure - - - - Verifies that two floats are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equals then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. All - non-numeric types are compared by using the Equals method. - Arrays are compared by comparing each element using the same rules. - If they are not equal an is thrown. - - The value that is expected - The actual value - The message to display if objects are not equal - Arguments to be used in formatting the message - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. All - non-numeric types are compared by using the Equals method. - If they are not equal an is thrown. - - The value that is expected - The actual value - The message to display if objects are not equal - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. All - non-numeric types are compared by using the Equals method. - If they are not equal an is thrown. - - The value that is expected - The actual value - - - - Asserts that two objects are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two objects are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two objects are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two ints are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two ints are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two ints are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two longss are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two longs are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two longs are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two uints are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two uints are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two uints are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two ulongs are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two ulongs are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two ulong are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two decimals are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two decimals are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two decimals are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two floats are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two floats are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two floats are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two doubles are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two doubles are not equal. If they are equal - an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two doubles are not equal. If they are equal - an is thrown. - - The expected object - The actual object - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are not the same object. - Arguments to be used in formatting the message - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - The message to be displayed when the object is null - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - The message to be displayed when the two objects are the same object. - Arguments to be used in formatting the message - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - The message to be displayed when the objects are the same - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - The message to display in case of failure - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - - - - Throws an with the message and arguments - that are passed in. This is used by the other Assert functions. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This is used by the other Assert functions. - - The message to initialize the with. - - - - Throws an . - This is used by the other Assert functions. - - - - - Throws an with the message and arguments - that are passed in. This causes the test to be reported as ignored. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This causes the test to be reported as ignored. - - The message to initialize the with. - - - - Throws an . - This causes the test to be reported as ignored. - - - - - NOTE: The use of asserters for extending NUnit has - now been replaced by the use of constraints. This - method is marked obsolete. - - Test the condition asserted by an asserter and throw - an assertion exception using provided message on failure. - - An object that implements IAsserter - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint to be applied - The actual value to test - - - - Apply a constraint to an actual value, succeedingt if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint to be applied - The actual value to test - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeedingt if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint to be applied - The actual value to test - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater or equal to than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater or equal to than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater or equal to than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than or equal to the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message that will be displayed on failure - - - - Verifies that the first value is greater than the second - value. If they are not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message that will be displayed on failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Gets the number of assertions executed so far and - resets the counter to zero. - - - - - Enumeration indicating how the expected message parameter is to be used - - - - Expect an exact match - - - Expect a message containing the parameter string - - - Match the regular expression provided as a parameter - - - - ExpectedExceptionAttribute - - - - - - Constructor for a non-specific exception - - - - - Constructor for a given type of exception - - The type of the expected exception - - - - Constructor for a given exception name - - The full name of the expected exception - - - - Constructor for a given type of exception and expected message text - - The type of the expected exception - The expected message text - - - - Constructor for a given exception name and expected message text - - The full name of the expected exception - The expected messge text - - - - Gets or sets the expected exception type - - - - - Gets or sets the full Type name of the expected exception - - - - - Gets or sets the expected message text - - - - - Gets or sets the user message displayed in case of failure - - - - - Gets or sets the type of match to be performed on the expected message - - - - - Gets the name of a method to be used as an exception handler - - - - - A set of Assert methods operationg on one or more collections - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - The message that will be displayed on failure - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable containing objects to be considered - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable containing objects to be considered - The message that will be displayed on failure - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - The message that will be displayed on failure - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - The message that will be displayed on failure - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that superset is not a subject of subset. - - The IEnumerable superset to be considered - The IEnumerable subset to be considered - - - - Asserts that superset is not a subject of subset. - - The IEnumerable superset to be considered - The IEnumerable subset to be considered - The message that will be displayed on failure - - - - Asserts that superset is not a subject of subset. - - The IEnumerable superset to be considered - The IEnumerable subset to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that superset is a subset of subset. - - The IEnumerable superset to be considered - The IEnumerable subset to be considered - - - - Asserts that superset is a subset of subset. - - The IEnumerable superset to be considered - The IEnumerable subset to be considered - The message that will be displayed on failure - - - - Asserts that superset is a subset of subset. - - The IEnumerable superset to be considered - The IEnumerable subset to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing IEnumerable - - - - NOTE: The use of asserters for extending NUnit has - now been replaced by the use of constraints. This - class is marked obsolete. - - AbstractAsserter is the base class for all asserters. - Asserters encapsulate a condition test and generation - of an AssertionException with a tailored message. They - are used by the Assert class as helper objects. - - User-defined asserters may be passed to the - Assert.DoAssert method in order to implement - extended asserts. - - - - - NOTE: The use of asserters for extending NUnit has - now been replaced by the use of constraints. This - interface is marked obsolete. - - The interface implemented by an asserter. Asserters - encapsulate a condition test and generation of an - AssertionException with a tailored message. They - are used by the Assert class as helper objects. - - User-defined asserters may be passed to the - Assert.DoAssert method in order to implement - extended asserts. - - - - - Test the condition for the assertion. - - True if the test succeeds - - - - Return the message giving the failure reason. - The return value is unspecified if no failure - has occured. - - - - - The user-defined message for this asserter. - - - - - Arguments to use in formatting the user-defined message. - - - - - Our failure message object, initialized as needed - - - - - Constructs an AbstractAsserter - - The message issued upon failure - Arguments to be used in formatting the message - - - - Test method to be implemented by derived types. - Default always succeeds. - - True if the test succeeds - - - - AssertionFailureMessage object used internally - - - - - Message related to a failure. If no failure has - occured, the result is unspecified. - - - - - The Assertion class is obsolete and has been - replaced by the Assert class. - - - - - Asserts that a condition is true. If it isn't it throws - an . - - The message to display is the condition - is false - The evaluated condition - - - - Asserts that a condition is true. If it isn't it throws - an . - - The evaluated condition - - - - /// Asserts that two doubles are equal concerning a delta. If the - expected value is infinity then the delta value is ignored. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - /// Asserts that two singles are equal concerning a delta. If the - expected value is infinity then the delta value is ignored. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - Asserts that two objects are equal. If they are not - an is thrown. - - - Asserts that two ints are equal. If they are not - an is thrown. - - - Asserts that two ints are equal. If they are not - an is thrown. - - - Asserts that two doubles are equal concerning a delta. - If the expected value is infinity then the delta value is ignored. - - - - Asserts that two floats are equal concerning a delta. - If the expected value is infinity then the delta value is ignored. - - - - - Asserts that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. Numeric - types are compared via string comparision on their contents to - avoid problems comparing values between different types. All - non-numeric types are compared by using the Equals method. - If they are not equal an is thrown. - - - - Asserts that an object isn't null. - - - Asserts that an object isn't null. - - - Asserts that an object is null. - - - Asserts that an object is null. - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - - - Asserts that two objects refer to the same object. - If they are not an is thrown. - - - - Fails a test with no message. - - - Fails a test with the given message. - - - - Thrown when an assertion failed. - - - - - The error message that explains - the reason for the exception - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - AssertionFailureMessage encapsulates a failure message - issued as a result of an Assert failure. - - - - - Number of characters before a highlighted position before - clipping will occur. Clipped text is replaced with an - elipsis "..." - - - - - Number of characters after a highlighted position before - clipping will occur. Clipped text is replaced with an - elipsis "..." - - - - - Prefix used to start an expected value line. - Must be same length as actualPrefix. - - - - - Prefix used to start an actual value line. - Must be same length as expectedPrefix. - - - - - Construct an AssertionFailureMessage with a message - and optional arguments. - - - - - - - Construct an empty AssertionFailureMessage - - - - - Add an expected value line to the message containing - the text provided as an argument. - - Text describing what was expected. - - - - Add an actual value line to the message containing - the text provided as an argument. - - Text describing the actual value. - - - - Add an expected value line to the message containing - a string representation of the object provided. - - An object representing the expected value - - - - Add an expected value line to the message containing a double - and the tolerance used in making the comparison. - - The expected value - The tolerance specified in the Assert - - - - Add an actual value line to the message containing - a string representation of the object provided. - - An object representing what was actually found - - - - Display two lines that communicate the expected value, and the actual value - - The expected value - The actual value found - - - - Display two lines that communicate the expected value, the actual value and - the tolerance used in comparing two doubles. - - The expected value - The actual value found - The tolerance specified in the Assert - - - - Draws a marker under the expected/actual strings that highlights - where in the string a mismatch occurred. - - The position of the mismatch - - - - Reports whether the string lengths are the same or different, and - what the string lengths are. - - The expected string - The actual string value - - - - Called to create additional message lines when two objects have been - found to be unequal. If the inputs are strings, a special message is - rendered that can help track down where the strings are different, - based on differences in length, or differences in content. - - If the inputs are not strings, the ToString method of the objects - is used to show what is different about them. - - The expected value - The actual value - True if a case-insensitive comparison is being performed - - - - Called to create additional message lines when two doubles have been - found to be unequal, within the specified tolerance. - - - - - Constructs a message that can be displayed when the content of two - strings are different, but the string lengths are the same. The - message will clip the strings to a reasonable length, centered - around the first position where they are mismatched, and draw - a line marking the position of the difference to make comparison - quicker. - - The expected string value - The actual string value - True if a case-insensitive comparison is being performed - - - - Display a standard message showing the differences found between - two arrays that were expected to be equal. - - The expected array value - The actual array value - The index at which a difference was found - - - - Display a standard message showing the differences found between - two collections that were expected to be equal. - - The expected collection value - The actual collection value - The index at which a difference was found - - - - Get an array of indices representing the point in a collection or - array corresponding to a single int index into the collection. - - The collection to which the indices apply - Index in the collection - Array of indices - - - - Displays elements from a list on a line - - Text to prefix the line with - The list of items to display - The index in the list of the first element to display - The maximum number of elements to display - - - - Formats an object for display in a message line - - The object to be displayed - - - - - Tests two objects to determine if they are strings. - - - - - - - - Renders up to M characters before, and up to N characters after - the specified index position. If leading or trailing text is - clipped, and elipses "..." is added where the missing text would - be. - - Clips strings to limit previous or post newline characters, - since these mess up the comparison - - - - - - - - Shows the position two strings start to differ. Comparison - starts at the start index. - - - - - -1 if no mismatch found, or the index where mismatch found - - - - Turns CR, LF, or TAB into visual indicator to preserve visual marker - position. This is done by replacing the '\r' into '\\' and 'r' - characters, and the '\n' into '\\' and 'n' characters, and '\t' into - '\\' and 't' characters. - - Thus the single character becomes two characters for display. - - - - - - - Attribute used to apply a category to a test - - - - - The name of the category - - - - - Construct attribute for a given category - - The name of the category - - - - Protected constructor uses the Type name as the name - of the category. - - - - - The name of the category - - - - - Abstract base for Attributes that are used to include tests - in the test run based on environmental settings. - - - - - Constructor with no included items specified, for use - with named property syntax. - - - - - Constructor taking one or more included items - - Comma-delimited list of included items - - - - Name of the item that is needed in order for - a test to run. Multiple itemss may be given, - separated by a comma. - - - - - Name of the item to be excluded. Multiple items - may be given, separated by a comma. - - - - - The reason for including or excluding the test - - - - - PlatformAttribute is used to mark a test fixture or an - individual method as applying to a particular platform only. - - - - - Constructor with no platforms specified, for use - with named property syntax. - - - - - Constructor taking one or more platforms - - Comma-deliminted list of platforms - - - - CultureAttribute is used to mark a test fixture or an - individual method as applying to a particular Culture only. - - - - - Constructor with no cultures specified, for use - with named property syntax. - - - - - Constructor taking one or more cultures - - Comma-deliminted list of cultures - - - - MessageWriter is the abstract base for classes that write - constraint descriptions and messages in some form. The - class has separate methods for writing various components - of a message, allowing implementations to tailor the - presentation as needed. - - - - - Construct a MessageWriter given a culture - - - - - Method to write single line message with optional args, usually - written to precede the general failure message. - - The message to be written - Any arguments used in formatting the message - - - - Method to write single line message with optional args, usually - written to precede the general failure message, at a givel - indentation level. - - The indentation level of the message - The message to be written - Any arguments used in formatting the message - - - - Display Expected and Actual lines for a constraint. This - is called by MessageWriter's default implementation of - WriteMessageTo and provides the generic two-line display. - - The constraint that failed - - - - Display Expected and Actual lines for given values. This - method may be called by constraints that need more control over - the display of actual and expected values than is provided - by the default implementation. - - The expected value - The actual value causing the failure - - - - Display Expected and Actual lines for given values, including - a tolerance value on the Expected line. - - The expected value - The actual value causing the failure - The tolerance within which the test was made - - - - Display the expected and actual string values on separate lines. - If the mismatch parameter is >=0, an additional line is displayed - line containing a caret that points to the mismatch point. - - The expected string value - The actual string value - The point at which the strings don't match or -1 - If true, case is ignored in locating the point where the strings differ - If true, the strings should be clipped to fit the line - - - - Writes the text for a connector. - - The connector. - - - - Writes the text for a predicate. - - The predicate. - - - - Writes the text for an expected value. - - The expected value. - - - - Writes the text for a modifier - - The modifier. - - - - Writes the text for an actual value. - - The actual value. - - - - Writes the text for a generalized value. - - The value. - - - - Writes the text for a collection value, - starting at a particular point, to a max length - - The collection containing elements to write. - The starting point of the elements to write - The maximum number of elements to write - - - - Abstract method to get the max line length - - - - - Static methods used in creating messages - - - - - Static string used when strings are clipped - - - - - Returns the representation of a type as used in NUnitLite. - This is the same as Type.ToString() except for arrays, - which are displayed with their declared sizes. - - - - - - - Converts any control characters in a string - to their escaped representation. - - The string to be converted - The converted string - - - - Return the a string representation for a set of indices into an array - - Array of indices for which a string is needed - - - - Get an array of indices representing the point in a collection or - array corresponding to a single int index into the collection. - - The collection to which the indices apply - Index in the collection - Array of indices - - - - Clip a string to a given length, starting at a particular offset, returning the clipped - string with ellipses representing the removed parts - - The string to be clipped - The maximum permitted length of the result string - The point at which to start clipping - The clipped string - - - - Clip the expected and actual strings in a coordinated fashion, - so that they may be displayed together. - - - - - - - - - Shows the position two strings start to differ. Comparison - starts at the start index. - - The expected string - The actual string - The index in the strings at which comparison should start - Boolean indicating whether case should be ignored - -1 if no mismatch found, or the index where mismatch found - - - - Summary description for SetCultureAttribute. - - - - - PropertyAttribute is used to attach information to a test as a name/value pair.. - - - - - The property name - - - - - The property value - - - - - Construct a PropertyAttribute with a name and value - - The name of the property - The property value - - - - Constructor for use by inherited classes that use the - name of the type as the property name. - - - - - Gets the property name - - - - - Gets the property value - - - - - Construct given the name of a culture - - - - - - TextMessageWriter writes constraint descriptions and messages - in displayable form as a text stream. It tailors the display - of individual message components to form the standard message - format of NUnit assertion failure messages. - - - - - Prefix used for the expected value line of a message - - - - - Prefix used for the actual value line of a message - - - - - Length of a message prefix - - - - - Construct a TextMessageWriter - - - - - Construct a TextMessageWriter, specifying a user message - and optional formatting arguments. - - - - - - - Method to write single line message with optional args, usually - written to precede the general failure message, at a givel - indentation level. - - The indentation level of the message - The message to be written - Any arguments used in formatting the message - - - - Display Expected and Actual lines for a constraint. This - is called by MessageWriter's default implementation of - WriteMessageTo and provides the generic two-line display. - - The constraint that failed - - - - Display Expected and Actual lines for given values. This - method may be called by constraints that need more control over - the display of actual and expected values than is provided - by the default implementation. - - The expected value - The actual value causing the failure - - - - Display Expected and Actual lines for given values, including - a tolerance value on the expected line. - - The expected value - The actual value causing the failure - The tolerance within which the test was made - - - - Display the expected and actual string values on separate lines. - If the mismatch parameter is >=0, an additional line is displayed - line containing a caret that points to the mismatch point. - - The expected string value - The actual string value - The point at which the strings don't match or -1 - If true, case is ignored in string comparisons - If true, clip the strings to fit the max line length - - - - Writes the text for a connector. - - The connector. - - - - Writes the text for a predicate. - - The predicate. - - - - Write the text for a modifier. - - The modifier. - - - - Writes the text for an expected value. - - The expected value. - - - - Writes the text for an actual value. - - The actual value. - - - - Writes the text for a generalized value. - - The value. - - - - Writes the text for a collection value, - starting at a particular point, to a max length - - The collection containing elements to write. - The starting point of the elements to write - The maximum number of elements to write - - - - Write the generic 'Expected' line for a constraint - - The constraint that failed - - - - Write the generic 'Expected' line for a given value - - The expected value - - - - Write the generic 'Expected' line for a given value - and tolerance. - - The expected value - The tolerance within which the test was made - - - - Write the generic 'Actual' line for a constraint - - The constraint for which the actual value is to be written - - - - Write the generic 'Actual' line for a given value - - The actual value causing a failure - - - - Gets or sets the maximum line length for this writer - - - - - Basic Asserts on strings. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - - - - Asserts that a string matches an expected regular expression pattern. - - The expected expression - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string matches an expected regular expression pattern. - - The expected expression - The actual string - The message to display in case of failure - - - - Asserts that a string matches an expected regular expression pattern. - - The expected expression - The actual string - - - - AssertionHelper is an optional base class for user tests, - allowing the use of shorter names for constraints and - asserts and avoiding conflict with the definition of - , from which it inherits much of its - behavior, in certain mock object frameworks. - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to - - A Constraint to be applied - The actual value to test - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to - - A Constraint to be applied - The actual value to test - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to - - A Constraint to be applied - The actual value to test - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to - . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to - . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to . - - The evaluated condition - - - - Returns a ListMapper based on a collection. - - The original collection - - - - - Summary description for FileAssert. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - The message to display if objects are not equal - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if objects are not equal - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if objects are not equal - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - The message to be displayed when the two Stream are the same. - Arguments to be used in formatting the message - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - The message to be displayed when the Streams are the same. - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if objects are not equal - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if objects are not equal - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - - - - Thrown when an assertion failed. - - - - - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - GlobalSettings is a place for setting default values used - by the framework in performing asserts. - - - - - Default tolerance for floating point equality - - - - - Obsolete class, formerly used to identify tests through - inheritance. Avoid using this class for new tests. - - - - - Method called immediately before running the test. - - - - - Method Called immediately after running the test. It is - guaranteed to be called, even if an exception is thrown. - - - - - Attribute used to mark a class that contains one-time SetUp - and/or TearDown methods that apply to all the tests in a - namespace or an assembly. - - - - - SetUpFixtureAttribute is used to identify a SetUpFixture - - - - - Attribute used to mark a static (shared in VB) property - that returns a list of tests. - - - - - Attribute used to identify a method that is called - immediately after each test is run. The method is - guaranteed to be called, even if an exception is thrown. - - - - - Adding this attribute to a method within a - class makes the method callable from the NUnit test runner. There is a property - called Description which is optional which you can provide a more detailed test - description. This class cannot be inherited. - - - - [TestFixture] - public class Fixture - { - [Test] - public void MethodToTest() - {} - - [Test(Description = "more detailed description")] - publc void TestDescriptionMethod() - {} - } - - - - - - Descriptive text for this test - - - - - [TestFixture] - public class ExampleClass - {} - - - - - Descriptive text for this fixture - - - - - Attribute used to identify a method that is - called before any tests in a fixture are run. - - - - - Attribute used to identify a method that is called after - all the tests in a fixture have run. The method is - guaranteed to be called, even if an exception is thrown. - - - - - Attribute used to mark a test that is to be ignored. - Ignored tests result in a warning message when the - tests are run. - - - - - Constructs the attribute without giving a reason - for ignoring the test. - - - - - Constructs the attribute giving a reason for ignoring the test - - The reason for ignoring the test - - - - The reason for ignoring a test - - - - - ExplicitAttribute marks a test or test fixture so that it will - only be run if explicitly executed from the gui or command line - or if it is included by use of a filter. The test will not be - run simply because an enclosing suite is run. - - - - - Default constructor - - - - - Constructor with a reason - - The reason test is marked explicit - - - - The reason test is marked explicit - - - - - Attribute used to provide descriptive text about a - test case or fixture. - - - - - Construct the attribute - - Text describing the test - - - - Gets the test description - - - - - Interface implemented by a user fixture in order to - validate any expected exceptions. It is only called - for test methods marked with the ExpectedException - attribute. - - - - - Method to handle an expected exception - - The exception to be handled - - - diff --git a/src/AllExamples.sln b/src/AllExamples.sln new file mode 100644 index 00000000..298e29bf --- /dev/null +++ b/src/AllExamples.sln @@ -0,0 +1,460 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceStack.Northwind", "ServiceStack.Northwind", "{206CDF5A-68B2-431A-B28D-B8F43C0697A6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceStack.Examples", "ServiceStack.Examples", "{A42B0FAF-687B-4E2A-845B-BF3D2B5FF6BC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hosts", "Hosts", "{2218422E-76B4-4128-ACFF-4CE824B0E0CE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StarterTemplates", "StarterTemplates", "{4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{73398563-F556-4345-80D3-E121F0AA84D2}" + ProjectSection(SolutionItems) = preProject + StarterTemplates\README.md = StarterTemplates\README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceStack.Hello", "ServiceStack.Hello", "{5AF13B19-7B73-4C74-BB82-A9640BBB58B4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceStack.MovieRest", "ServiceStack.MovieRest", "{D217E359-75BD-4875-817A-40A4819C4E83}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RedisStackOverflow", "RedisStackOverflow", "{68A679AC-8B0D-45A4-8624-68C706089DEE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RestFiles", "RestFiles", "{EBC6AB0B-D961-4E31-A2B4-09F74F102B37}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RestIntro", "RestIntro", "{45340404-FACD-4C79-9703-95966FEA84E3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backbone.Todos", "Backbone.Todos", "{79CD1278-66D5-458A-B75D-06EF4CC050A9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{ABD851F4-394B-4999-BCD2-12CE41BEFE9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Northwind", "ServiceStack.Northwind\ServiceStack.Northwind\ServiceStack.Northwind.csproj", "{3E968D84-7C23-42E9-A443-6355FAA845E2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Northwind.ServiceModel", "ServiceStack.Northwind\ServiceStack.Northwind.ServiceModel\ServiceStack.Northwind.ServiceModel.csproj", "{14856482-95D3-4A02-968C-665F3D08F94D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Northwind.ServiceInterface", "ServiceStack.Northwind\ServiceStack.Northwind.ServiceInterface\ServiceStack.Northwind.ServiceInterface.csproj", "{A724F80D-4341-4ECA-AC43-CF84A3F03779}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.Host.Web", "ServiceStack.Examples\ServiceStack.Examples.Host.Web\ServiceStack.Examples.Host.Web.csproj", "{3A8D2349-6E97-47A2-AC49-EFE7D89C0344}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.ServiceInterface", "ServiceStack.Examples\ServiceStack.Examples.ServiceInterface\ServiceStack.Examples.ServiceInterface.csproj", "{519A7B72-D144-436D-AAC3-7BAAEAD3FF52}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.Host.Console", "ServiceStack.Examples\ServiceStack.Examples.Host.Console\ServiceStack.Examples.Host.Console.csproj", "{77363223-98F2-4724-8044-569C6485B3A9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.Clients", "ServiceStack.Examples\ServiceStack.Examples.Clients\ServiceStack.Examples.Clients.csproj", "{53F87D5C-4540-4AFD-BD19-E081FD8E586B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.ServiceModel", "ServiceStack.Examples\ServiceStack.Examples.ServiceModel\ServiceStack.Examples.ServiceModel.csproj", "{2B840832-3036-47D9-8F9B-560CD5C2BF90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StarterTemplates.Common", "StarterTemplates\StarterTemplates.Common\StarterTemplates.Common.csproj", "{ACBF3D12-379A-41D7-87DB-C376CFCBD131}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleAppHost", "StarterTemplates\ConsoleAppHost\ConsoleAppHost.csproj", "{79950922-9EFF-44E1-993A-4EA20DEC780A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinServiceAppHost", "StarterTemplates\WinServiceAppHost\WinServiceAppHost.csproj", "{D49ABE7E-B090-4473-B80B-B2432BBF8CB5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Hello", "ServiceStack.Hello\ServiceStack.Hello.csproj", "{A8F9A08B-E704-4C77-939B-B56670A2A98D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStackOverflow.ServiceInterface", "RedisStackOverflow\RedisStackOverflow.ServiceInterface\RedisStackOverflow.ServiceInterface.csproj", "{41C8C157-B2A4-4DDE-B153-233E46109F39}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStackOverflow", "RedisStackOverflow\RedisStackOverflow\RedisStackOverflow.csproj", "{CCAC74EA-08EE-41A8-BF01-8F1B7D207144}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestFiles", "RestFiles\RestFiles\RestFiles.csproj", "{70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestFiles.ServiceInterface", "RestFiles\RestFiles.ServiceInterface\RestFiles.ServiceInterface.csproj", "{5B91935A-7ED6-4496-871B-6AD25BC3F097}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestFiles.ServiceModel", "RestFiles\RestFiles.ServiceModel\RestFiles.ServiceModel.csproj", "{6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestIntro", "RestIntro\RestIntro\RestIntro.csproj", "{2E71EB42-595D-4181-A27B-BD85DCA739D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestIntro.ServiceModel", "RestIntro\RestIntro.ServiceModel\RestIntro.ServiceModel.csproj", "{8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestIntro.ServiceInterface", "RestIntro\RestIntro.ServiceInterface\RestIntro.ServiceInterface.csproj", "{CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backbone.Todos", "Backbone.Todos\Backbone.Todos.csproj", "{BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Docs", "Docs\Docs.csproj", "{19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Docs.Logic", "Docs\Docs.Logic\Docs.Logic.csproj", "{2A606EB5-47BD-47B1-97EB-8C208DF63ABF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStackOverflow.ServiceModel", "RedisStackOverflow\RedisStackOverflow.ServiceModel\RedisStackOverflow.ServiceModel.csproj", "{BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.MovieRest", "ServiceStack.MovieRest\Web\ServiceStack.MovieRest.csproj", "{EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1DE83058-60D9-4637-90EF-C3E46EAA9ACC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.Tests", "..\tests\ServiceStack.Examples.Tests\ServiceStack.Examples.Tests.csproj", "{969644BC-B209-4458-8DC1-041D7A9ADD3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.Examples.Tests.Integration", "..\tests\ServiceStack.Examples.Tests.Integration\ServiceStack.Examples.Tests.Integration.csproj", "{21777EAF-74FD-4D0B-947A-C602D8D3EBBA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestFiles.Tests", "RestFiles\RestFiles.Tests\RestFiles.Tests.csproj", "{DAE4FFC2-B446-4020-8578-19B816FAA40A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RootPath45", "StarterTemplates\RootPath45\RootPath45.csproj", "{91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{19FF9025-F307-4507-9CCB-5D08D7D975E1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomPath45", "StarterTemplates\CustomPath45\CustomPath45.csproj", "{E256695F-8607-4A79-ABA5-6FED3A400C71}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Debug|x86.ActiveCfg = Debug|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Release|Any CPU.Build.0 = Release|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3E968D84-7C23-42E9-A443-6355FAA845E2}.Release|x86.ActiveCfg = Release|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Debug|x86.ActiveCfg = Debug|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Release|Any CPU.Build.0 = Release|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {14856482-95D3-4A02-968C-665F3D08F94D}.Release|x86.ActiveCfg = Release|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Debug|x86.ActiveCfg = Debug|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Release|Any CPU.Build.0 = Release|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A724F80D-4341-4ECA-AC43-CF84A3F03779}.Release|x86.ActiveCfg = Release|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Debug|x86.ActiveCfg = Debug|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Release|Any CPU.Build.0 = Release|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344}.Release|x86.ActiveCfg = Release|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Debug|x86.ActiveCfg = Debug|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Release|Any CPU.Build.0 = Release|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52}.Release|x86.ActiveCfg = Release|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Debug|x86.ActiveCfg = Debug|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Release|Any CPU.Build.0 = Release|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {77363223-98F2-4724-8044-569C6485B3A9}.Release|x86.ActiveCfg = Release|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Debug|x86.ActiveCfg = Debug|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Release|Any CPU.Build.0 = Release|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {53F87D5C-4540-4AFD-BD19-E081FD8E586B}.Release|x86.ActiveCfg = Release|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Debug|x86.ActiveCfg = Debug|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Release|Any CPU.Build.0 = Release|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2B840832-3036-47D9-8F9B-560CD5C2BF90}.Release|x86.ActiveCfg = Release|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Debug|x86.ActiveCfg = Debug|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Release|Any CPU.Build.0 = Release|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ACBF3D12-379A-41D7-87DB-C376CFCBD131}.Release|x86.ActiveCfg = Release|Any CPU + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Debug|Any CPU.ActiveCfg = Debug|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Debug|Any CPU.Build.0 = Debug|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Debug|x86.ActiveCfg = Debug|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Debug|x86.Build.0 = Debug|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Release|Any CPU.ActiveCfg = Release|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Release|Any CPU.Build.0 = Release|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Release|Mixed Platforms.Build.0 = Release|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Release|x86.ActiveCfg = Release|x86 + {79950922-9EFF-44E1-993A-4EA20DEC780A}.Release|x86.Build.0 = Release|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Debug|Any CPU.ActiveCfg = Debug|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Debug|Any CPU.Build.0 = Debug|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Debug|x86.ActiveCfg = Debug|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Debug|x86.Build.0 = Debug|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Release|Any CPU.ActiveCfg = Release|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Release|Any CPU.Build.0 = Release|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Release|Mixed Platforms.Build.0 = Release|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Release|x86.ActiveCfg = Release|x86 + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5}.Release|x86.Build.0 = Release|x86 + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Debug|x86.ActiveCfg = Debug|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Release|Any CPU.Build.0 = Release|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A8F9A08B-E704-4C77-939B-B56670A2A98D}.Release|x86.ActiveCfg = Release|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Debug|x86.ActiveCfg = Debug|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Release|Any CPU.Build.0 = Release|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {41C8C157-B2A4-4DDE-B153-233E46109F39}.Release|x86.ActiveCfg = Release|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Debug|x86.ActiveCfg = Debug|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|Any CPU.Build.0 = Release|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|x86.ActiveCfg = Release|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Debug|x86.ActiveCfg = Debug|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Release|Any CPU.Build.0 = Release|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB}.Release|x86.ActiveCfg = Release|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Debug|x86.ActiveCfg = Debug|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Release|Any CPU.Build.0 = Release|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5B91935A-7ED6-4496-871B-6AD25BC3F097}.Release|x86.ActiveCfg = Release|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Debug|x86.ActiveCfg = Debug|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Release|Any CPU.Build.0 = Release|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF}.Release|x86.ActiveCfg = Release|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Release|Any CPU.Build.0 = Release|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2E71EB42-595D-4181-A27B-BD85DCA739D1}.Release|x86.ActiveCfg = Release|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Debug|x86.ActiveCfg = Debug|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Release|Any CPU.Build.0 = Release|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114}.Release|x86.ActiveCfg = Release|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Debug|x86.ActiveCfg = Debug|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Release|Any CPU.Build.0 = Release|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10}.Release|x86.ActiveCfg = Release|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Debug|x86.ActiveCfg = Debug|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Release|Any CPU.Build.0 = Release|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2}.Release|x86.ActiveCfg = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|x86.ActiveCfg = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Any CPU.Build.0 = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|x86.ActiveCfg = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|x86.ActiveCfg = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Any CPU.Build.0 = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|x86.ActiveCfg = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|x86.ActiveCfg = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|Any CPU.Build.0 = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|x86.ActiveCfg = Release|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|x86.ActiveCfg = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Any CPU.Build.0 = Release|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|x86.ActiveCfg = Release|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Debug|x86.ActiveCfg = Debug|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Release|Any CPU.Build.0 = Release|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {969644BC-B209-4458-8DC1-041D7A9ADD3B}.Release|x86.ActiveCfg = Release|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Debug|x86.ActiveCfg = Debug|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Release|Any CPU.Build.0 = Release|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA}.Release|x86.ActiveCfg = Release|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Debug|x86.ActiveCfg = Debug|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Debug|x86.Build.0 = Debug|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Release|Any CPU.Build.0 = Release|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Release|x86.ActiveCfg = Release|Any CPU + {DAE4FFC2-B446-4020-8578-19B816FAA40A}.Release|x86.Build.0 = Release|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Debug|x86.ActiveCfg = Debug|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Debug|x86.Build.0 = Debug|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Release|Any CPU.Build.0 = Release|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Release|x86.ActiveCfg = Release|Any CPU + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F}.Release|x86.Build.0 = Release|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Debug|x86.ActiveCfg = Debug|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Debug|x86.Build.0 = Debug|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Release|Any CPU.Build.0 = Release|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Release|x86.ActiveCfg = Release|Any CPU + {E256695F-8607-4A79-ABA5-6FED3A400C71}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2218422E-76B4-4128-ACFF-4CE824B0E0CE} = {A42B0FAF-687B-4E2A-845B-BF3D2B5FF6BC} + {73398563-F556-4345-80D3-E121F0AA84D2} = {4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02} + {3E968D84-7C23-42E9-A443-6355FAA845E2} = {206CDF5A-68B2-431A-B28D-B8F43C0697A6} + {14856482-95D3-4A02-968C-665F3D08F94D} = {206CDF5A-68B2-431A-B28D-B8F43C0697A6} + {A724F80D-4341-4ECA-AC43-CF84A3F03779} = {206CDF5A-68B2-431A-B28D-B8F43C0697A6} + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344} = {2218422E-76B4-4128-ACFF-4CE824B0E0CE} + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52} = {A42B0FAF-687B-4E2A-845B-BF3D2B5FF6BC} + {77363223-98F2-4724-8044-569C6485B3A9} = {2218422E-76B4-4128-ACFF-4CE824B0E0CE} + {53F87D5C-4540-4AFD-BD19-E081FD8E586B} = {2218422E-76B4-4128-ACFF-4CE824B0E0CE} + {2B840832-3036-47D9-8F9B-560CD5C2BF90} = {A42B0FAF-687B-4E2A-845B-BF3D2B5FF6BC} + {ACBF3D12-379A-41D7-87DB-C376CFCBD131} = {4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02} + {79950922-9EFF-44E1-993A-4EA20DEC780A} = {4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02} + {D49ABE7E-B090-4473-B80B-B2432BBF8CB5} = {4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02} + {A8F9A08B-E704-4C77-939B-B56670A2A98D} = {5AF13B19-7B73-4C74-BB82-A9640BBB58B4} + {41C8C157-B2A4-4DDE-B153-233E46109F39} = {68A679AC-8B0D-45A4-8624-68C706089DEE} + {CCAC74EA-08EE-41A8-BF01-8F1B7D207144} = {68A679AC-8B0D-45A4-8624-68C706089DEE} + {70B9EEDE-BC2A-42EB-933D-A94D7D4275CB} = {EBC6AB0B-D961-4E31-A2B4-09F74F102B37} + {5B91935A-7ED6-4496-871B-6AD25BC3F097} = {EBC6AB0B-D961-4E31-A2B4-09F74F102B37} + {6BBEDCA5-1183-49EE-AE80-0269DEB2EDEF} = {EBC6AB0B-D961-4E31-A2B4-09F74F102B37} + {2E71EB42-595D-4181-A27B-BD85DCA739D1} = {45340404-FACD-4C79-9703-95966FEA84E3} + {8ED227D1-0C83-4A1D-91D0-1B9DFCD8E114} = {45340404-FACD-4C79-9703-95966FEA84E3} + {CBC26F2A-3B89-4DA4-A5A0-7C05A48EAF10} = {45340404-FACD-4C79-9703-95966FEA84E3} + {BDE04BD3-40A0-4B8E-A0B9-7729FFB7D1C2} = {79CD1278-66D5-458A-B75D-06EF4CC050A9} + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F} = {ABD851F4-394B-4999-BCD2-12CE41BEFE9D} + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF} = {ABD851F4-394B-4999-BCD2-12CE41BEFE9D} + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14} = {68A679AC-8B0D-45A4-8624-68C706089DEE} + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C} = {D217E359-75BD-4875-817A-40A4819C4E83} + {1DE83058-60D9-4637-90EF-C3E46EAA9ACC} = {A42B0FAF-687B-4E2A-845B-BF3D2B5FF6BC} + {969644BC-B209-4458-8DC1-041D7A9ADD3B} = {1DE83058-60D9-4637-90EF-C3E46EAA9ACC} + {21777EAF-74FD-4D0B-947A-C602D8D3EBBA} = {1DE83058-60D9-4637-90EF-C3E46EAA9ACC} + {DAE4FFC2-B446-4020-8578-19B816FAA40A} = {19FF9025-F307-4507-9CCB-5D08D7D975E1} + {91D8B4E8-1973-40C6-AF44-DBFEEAAF0C7F} = {4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02} + {19FF9025-F307-4507-9CCB-5D08D7D975E1} = {EBC6AB0B-D961-4E31-A2B4-09F74F102B37} + {E256695F-8607-4A79-ABA5-6FED3A400C71} = {4721A7AC-65B8-48C0-A7CC-BF4B7A2B9D02} + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = ..\Client\RemoteInfoClient\RemoteInfoClient.csproj + EndGlobalSection +EndGlobal diff --git a/src/AllExamples.sln.DotSettings b/src/AllExamples.sln.DotSettings new file mode 100644 index 00000000..11f2c267 --- /dev/null +++ b/src/AllExamples.sln.DotSettings @@ -0,0 +1,3 @@ + + <data><IncludeFilters /><ExcludeFilters /></data> + <data /> \ No newline at end of file diff --git a/src/Backbone.Todos/Backbone.Todos.csproj b/src/Backbone.Todos/Backbone.Todos.csproj index e82b9ae5..066a9f92 100644 --- a/src/Backbone.Todos/Backbone.Todos.csproj +++ b/src/Backbone.Todos/Backbone.Todos.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -12,7 +13,19 @@ Properties Backbone.Todos Backbone.Todos - v3.5 + v4.5 + true + + + + + 4.0 + + + + + + true @@ -22,6 +35,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -30,39 +44,46 @@ TRACE prompt 4 + false - - False - ..\..\lib\ServiceStack.dll + + ..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True - - False - ..\..\lib\ServiceStack.Common.dll + + ..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True - - False - ..\..\lib\ServiceStack.Interfaces.dll + + ..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True - - False - ..\..\lib\ServiceStack.Redis.dll + + ..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True - - False - ..\..\lib\ServiceStack.ServiceInterface.dll + + ..\packages\ServiceStack.Redis.4.5.0\lib\net45\ServiceStack.Redis.dll + True - - ..\..\lib\ServiceStack.Text.dll + + ..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True - + + + + + + - + @@ -80,11 +101,11 @@ - - - - - + + + + + @@ -93,9 +114,16 @@ - + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + - + + @@ -104,7 +132,7 @@ True 11809 / - http://localhost/Backbone.Todos + http://localhost:11809/ False False @@ -113,6 +141,11 @@ + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/Backbone.Todos/default.htm b/src/Backbone.Todos/default.htm index 2113a076..a08250b3 100644 --- a/src/Backbone.Todos/default.htm +++ b/src/Backbone.Todos/default.htm @@ -1,68 +1,60 @@ - - + Backbone Demo: Todos - - - - - - - - - - ServiceStack Home - + + + + + + + + + + ServiceStack Home + -
- -
-

Todos

-
- -
- -
- - +
+

+ Todos

- -
-
    +
    +
    + + +
    +
    +
      +
    +
    +
    +
    - -
    - -
    -
    - -
    - Created by -
    - Jérôme Gravel-Niquet -
    -
    - Powered By Open Source -
    - servicestack.net - | redis - | mono + Created by +
    + Jérôme Gravel-Niquet +
    +
    + Powered By Open Source +
    + servicestack.net | redis + | mono
    - - - - - - - - - - + + diff --git a/src/Backbone.Todos/packages.config b/src/Backbone.Todos/packages.config new file mode 100644 index 00000000..1b4c7602 --- /dev/null +++ b/src/Backbone.Todos/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Backbone.Todos/packages/ServiceStack.4.0.11/ServiceStack.4.0.11.nupkg b/src/Backbone.Todos/packages/ServiceStack.4.0.11/ServiceStack.4.0.11.nupkg new file mode 100644 index 00000000..4ec38fea Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.4.0.11/ServiceStack.4.0.11.nupkg differ diff --git a/src/Backbone.Todos/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.dll b/src/Backbone.Todos/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.dll new file mode 100644 index 00000000..83933d41 Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.xml b/src/Backbone.Todos/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.xml new file mode 100644 index 00000000..d238a55a --- /dev/null +++ b/src/Backbone.Todos/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.xml @@ -0,0 +1,8174 @@ + + + + ServiceStack + + + + + Base class to create request filter attributes only for specific HTTP methods (GET, POST...) + + + + + Creates a new + + Defines when the filter should be executed + + + + This method is only executed if the HTTP method matches the property. + + The http request wrapper + The http response wrapper + The request DTO + + + + Create a ShallowCopy of this instance. + + + + + + Inherit from this class if you want to host your web services inside a + Console Application, Windows Service, etc. + + Usage of HttpListener allows you to host webservices on the same port (:80) as IIS + however it requires admin user privillages. + + + + + Wrapper class for the HTTPListener to allow easier access to the + server, for start and stop management and event routing of the actual + inbound requests. + + + + + ASP.NET or HttpListener ServiceStack host + + + + + Register dependency in AppHost IOC on Startup + + + + + AutoWired Registration of an interface with a concrete type in AppHost IOC on Startup. + + + + + Allows the clean up for executed autowired services and filters. + Calls directly after services and filters are executed. + + + + + Called at the end of each request. Enables Request Scope. + + + + + Register an Adhoc web service on Startup + + + + + Apply plugins to this AppHost + + + + + Create a service runner for IService actions + + + + + Resolve the absolute url for this request + + + + + Resolve localized text, returns itself by default. + + + + + Register user-defined custom routes. + + + + + Register custom ContentType serializers + + + + + Add Request Filters, to be applied before the dto is deserialized + + + + + Add Request Filters for HTTP Requests + + + + + Add Response Filters for HTTP Responses + + + + + Add Request Filters for MQ/TCP Requests + + + + + Add Response Filters for MQ/TCP Responses + + + + + Add alternative HTML View Engines + + + + + Provide an exception handler for unhandled exceptions + + + + + Provide an exception handler for un-caught exceptions + + + + + Skip the ServiceStack Request Pipeline and process the returned IHttpHandler instead + + + + + Provide a catch-all handler that doesn't match any routes + + + + + Use a Custom Error Handler for handling specific error HttpStatusCodes + + + + + Provide a custom model minder for a specific Request DTO + + + + + The AppHost config + + + + + List of pre-registered and user-defined plugins to be enabled in this AppHost + + + + + Virtual access to file resources + + + + + Funqlets are a set of components provided as a package + to an existing container (like a module). + + + + + Configure the given container with the + registrations provided by the funqlet. + + Container to register. + + + + Executed immediately before a Service is executed. Use return to change the request DTO used, must be of the same type. + + + + + Executed immediately after a service is executed. Use return to change response used. + + + + + Occurs when the Service throws an Exception. + + + + + Occurs when an exception is thrown whilst processing a request. + + + + + Apply PreRequest Filters for participating Custom Handlers, e.g. RazorFormat, MarkdownFormat, etc + + + + + Applies the raw request filters. Returns whether or not the request has been handled + and no more processing should be done. + + + + + + Applies the request filters. Returns whether or not the request has been handled + and no more processing should be done. + + + + + + Applies the response filters. Returns whether or not the request has been handled + and no more processing should be done. + + + + + + The AppHost.Container. Note: it is not thread safe to register dependencies after AppStart. + + + + + Starts the Web Service + + + A Uri that acts as the base that the server is listening on. + Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/ + Note: the trailing slash is required! For more info see the + HttpListener.Prefixes property on MSDN. + + + + + Shut down the Web Service + + + + + Overridable method that can be used to implement a custom hnandler + + + + + + Reserves the specified URL for non-administrator users and accounts. + http://msdn.microsoft.com/en-us/library/windows/desktop/cc307223(v=vs.85).aspx + + Reserved Url if the process completes successfully + + + + Creates the required missing tables or DB schema + + + + + Redirect to the https:// version of this url if not already. + + + + + Don't redirect when in DebugMode + + + + + Don't redirect if the request was a forwarded request, e.g. from a Load Balancer + + + + + Single threaded message handler that can process all messages + of a particular message type. + + + + + Process all messages pending + + + + + + Process messages from a single queue. + + + The queue to process + A predicate on whether to continue processing the next message if any + + + + + Process a single message + + + + + Get Current Stats for this Message Handler + + + + + + The type of the message this handler processes + + + + + Encapsulates creating a new message handler + + + + + Processes all messages in a Normal and Priority Queue. + Expects to be called in 1 thread. i.e. Non Thread-Safe. + + + + + + A convenient repository base class you can inherit from to reduce the boilerplate + with accessing a managed IDbConnection + + + + + A convenient base class for your injected service dependencies that reduces the boilerplate + with managed access to ServiceStack's built-in providers + + + + + This class stores the caller call context in order to restore + it when the work item is executed in the thread pool environment. + + + + + Constructor + + + + + Captures the current thread context + + + + + + Applies the thread context stored earlier + + + + + + EventWaitHandleFactory class. + This is a static class that creates AutoResetEvent and ManualResetEvent objects. + In WindowCE the WaitForMultipleObjects API fails to use the Handle property + of XxxResetEvent. It can use only handles that were created by the CreateEvent API. + Consequently this class creates the needed XxxResetEvent and replaces the handle if + it's a WindowsCE OS. + + + + + Create a new AutoResetEvent object + + Return a new AutoResetEvent object + + + + Create a new ManualResetEvent object + + Return a new ManualResetEvent object + + + + Represents an exception in case IWorkItemResult.GetResult has been canceled + + + Represents an exception in case IWorkItemResult.GetResult has been canceled + + + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + + + A delegate that represents the method to run as the work item + + A state object for the method to run + + + + A delegate to call after the WorkItemCallback completed + + The work item result object + + + + A delegate to call after the WorkItemCallback completed + + The work item result object + + + + A delegate to call when a WorkItemsGroup becomes idle + + A reference to the WorkItemsGroup that became idle + + + + A delegate to call after a thread is created, but before + it's first use. + + + + + A delegate to call when a thread is about to exit, after + it is no longer belong to the pool. + + + + + Defines the availeable priorities of a work item. + The higher the priority a work item has, the sooner + it will be executed. + + + + + IWorkItemsGroup interface + Created by SmartThreadPool.CreateWorkItemsGroup() + + + + + Get an array with all the state objects of the currently running items. + The array represents a snap shot and impact performance. + + + + + Starts to execute work items + + + + + Cancel all the work items. + Same as Cancel(false) + + + + + Cancel all work items using thread abortion + + True to stop work items by raising ThreadAbortException + + + + Wait for all work item to complete. + + + + + Wait for all work item to complete, until timeout expired + + How long to wait for the work items to complete + Returns true if work items completed within the timeout, otherwise false. + + + + Wait for all work item to complete, until timeout expired + + How long to wait for the work items to complete in milliseconds + Returns true if work items completed within the timeout, otherwise false. + + + + Queue a work item + + A callback to execute + Returns a work item result + + + + Queue a work item + + A callback to execute + The priority of the work item + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + The work item priority + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + The work item priority + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + The work item priority + Returns a work item result + + + + Queue a work item + + Work item info + A callback to execute + Returns a work item result + + + + Queue a work item + + Work item information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Get/Set the name of the WorkItemsGroup + + + + + Get/Set the maximum number of workitem that execute cocurrency on the thread pool + + + + + Get the number of work items waiting in the queue. + + + + + Get the WorkItemsGroup start information + + + + + IsIdle is true when there are no work items running or queued. + + + + + This event is fired when all work items are completed. + (When IsIdle changes to true) + This event only work on WorkItemsGroup. On SmartThreadPool + it throws the NotImplementedException. + + + + + Never call to the PostExecute call back + + + + + Call to the PostExecute only when the work item is cancelled + + + + + Call to the PostExecute only when the work item is not cancelled + + + + + Always call to the PostExecute + + + + + The common interface of IWorkItemResult and IWorkItemResult<T> + + + + + This method intent is for internal use. + + + + + + This method intent is for internal use. + + + + + + IWorkItemResult interface. + Created when a WorkItemCallback work item is queued. + + + + + IWorkItemResult<TResult> interface. + Created when a Func<TResult> work item is queued. + + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits. + + The result of the work item + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + Timeout in milliseconds, or -1 for infinite + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the blocking if needed + The result of the work item + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + The result of the work item + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits. + + Filled with the exception if one was thrown + The result of the work item + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + + + Filled with the exception if one was thrown + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + + Filled with the exception if one was thrown + + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + Timeout in milliseconds, or -1 for infinite + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the blocking if needed + Filled with the exception if one was thrown + The result of the work item + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + The result of the work item + + Filled with the exception if one was thrown + + + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Same as Cancel(false). + + + + + Cancel the work item execution. + If the work item is in the queue then it won't execute + If the work item is completed, it will remain completed + If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled + property to check if the work item has been cancelled. If the abortExecution is set to true then + the Smart Thread Pool will send an AbortException to the running thread to stop the execution + of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException. + If the work item is already cancelled it will remain cancelled + + When true send an AbortException to the executing thread. + Returns true if the work item was not completed, otherwise false. + + + + Gets an indication whether the asynchronous operation has completed. + + + + + Gets an indication whether the asynchronous operation has been canceled. + + + + + Gets the user-defined object that contains context data + for the work item method. + + + + + Get the work item's priority + + + + + Return the result, same as GetResult() + + + + + Returns the exception if occured otherwise returns null. + + + + + An internal delegate to call when the WorkItem starts or completes + + + + + This method is intent for internal use. + + + + + PriorityQueue class + This class is not thread safe because we use external lock + + + + + The number of queues, there is one for each type of priority + + + + + Work items queues. There is one for each type of priority + + + + + The total number of work items within the queues + + + + + Use with IEnumerable interface + + + + + Enqueue a work item. + + A work item + + + + Dequeque a work item. + + Returns the next work item + + + + Find the next non empty queue starting at queue queueIndex+1 + + The index-1 to start from + + The index of the next non empty queue or -1 if all the queues are empty + + + + + Clear all the work items + + + + + Returns an enumerator to iterate over the work items + + Returns an enumerator + + + + The number of work items + + + + + The class the implements the enumerator + + + + + Smart thread pool class. + + + + + Contains the name of this instance of SmartThreadPool. + Can be changed by the user. + + + + + Cancel all the work items. + Same as Cancel(false) + + + + + Wait for the SmartThreadPool/WorkItemsGroup to be idle + + + + + Wait for the SmartThreadPool/WorkItemsGroup to be idle + + + + + Queue a work item + + A callback to execute + Returns a work item result + + + + Queue a work item + + A callback to execute + The priority of the work item + Returns a work item result + + + + Queue a work item + + Work item info + A callback to execute + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + The work item priority + Returns a work item result + + + + Queue a work item + + Work item information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + The work item priority + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + The work item priority + Returns a work item result + + + + Get/Set the name of the SmartThreadPool/WorkItemsGroup instance + + + + + IsIdle is true when there are no work items running or queued. + + + + + Default minimum number of threads the thread pool contains. (0) + + + + + Default maximum number of threads the thread pool contains. (25) + + + + + Default idle timeout in milliseconds. (One minute) + + + + + Indicate to copy the security context of the caller and then use it in the call. (false) + + + + + Indicate to copy the HTTP context of the caller and then use it in the call. (false) + + + + + Indicate to dispose of the state objects if they support the IDispose interface. (false) + + + + + The default option to run the post execute (CallToPostExecute.Always) + + + + + The default work item priority (WorkItemPriority.Normal) + + + + + The default is to work on work items as soon as they arrive + and not to wait for the start. (false) + + + + + The default thread priority (ThreadPriority.Normal) + + + + + The default thread pool name. (SmartThreadPool) + + + + + The default fill state with params. (false) + It is relevant only to QueueWorkItem of Action<...>/Func<...> + + + + + The default thread backgroundness. (true) + + + + + The default apartment state of a thread in the thread pool. + The default is ApartmentState.Unknown which means the STP will not + set the apartment of the thread. It will use the .NET default. + + + + + The default post execute method to run. (None) + When null it means not to call it. + + + + + The default name to use for the performance counters instance. (null) + + + + + The default Max Stack Size. (SmartThreadPool) + + + + + Dictionary of all the threads in the thread pool. + + + + + Queue of work items. + + + + + Count the work items handled. + Used by the performance counter. + + + + + Number of threads that currently work (not idle). + + + + + Stores a copy of the original STPStartInfo. + It is used to change the MinThread and MaxThreads + + + + + Total number of work items that are stored in the work items queue + plus the work items that the threads in the pool are working on. + + + + + Signaled when the thread pool is idle, i.e. no thread is busy + and the work items queue is empty + + + + + An event to signal all the threads to quit immediately. + + + + + A flag to indicate if the Smart Thread Pool is now suspended. + + + + + A flag to indicate the threads to quit. + + + + + Counts the threads created in the pool. + It is used to name the threads. + + + + + Indicate that the SmartThreadPool has been disposed + + + + + Holds all the WorkItemsGroup instaces that have at least one + work item int the SmartThreadPool + This variable is used in case of Shutdown + + + + + A common object for all the work items int the STP + so we can mark them to cancel in O(1) + + + + + Windows STP performance counters + + + + + Local STP performance counters + + + + + Constructor + + + + + Constructor + + Idle timeout in milliseconds + + + + Constructor + + Idle timeout in milliseconds + Upper limit of threads in the pool + + + + Constructor + + Idle timeout in milliseconds + Upper limit of threads in the pool + Lower limit of threads in the pool + + + + Constructor + + A SmartThreadPool configuration that overrides the default behavior + + + + Waits on the queue for a work item, shutdown, or timeout. + + + Returns the WaitingCallback or null in case of timeout or shutdown. + + + + + Put a new work item in the queue + + A work item to queue + + + + Inform that the current thread is about to quit or quiting. + The same thread may call this method more than once. + + + + + Starts new threads + + The number of threads to start + + + + A worker thread method that processes work items from the work items queue. + + + + + Force the SmartThreadPool to shutdown + + + + + Force the SmartThreadPool to shutdown with timeout + + + + + Empties the queue of work items and abort the threads in the pool. + + + + + Wait for all work items to complete + + Array of work item result objects + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + true when every work item in workItemResults has completed; otherwise false. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + + The array index of the work item result that satisfied the wait, or WaitTimeout if any of the work items has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Creates a new WorkItemsGroup. + + The number of work items that can be run concurrently + A reference to the WorkItemsGroup + + + + Creates a new WorkItemsGroup. + + The number of work items that can be run concurrently + A WorkItemsGroup configuration that overrides the default behavior + A reference to the WorkItemsGroup + + + + Checks if the work item has been cancelled, and if yes then abort the thread. + Can be used with Cancel and timeout + + + + + Get an array with all the state objects of the currently running items. + The array represents a snap shot and impact performance. + + + + + Start the thread pool if it was started suspended. + If it is already running, this method is ignored. + + + + + Cancel all work items using thread abortion + + True to stop work items by raising ThreadAbortException + + + + Wait for the thread pool to be idle + + + + + Executes all actions in parallel. + Returns when they all finish. + + Actions to execute + + + + Executes all actions in parallel. + Returns when they all finish. + + Actions to execute + + + + Executes all actions in parallel + Returns when the first one completes + + Actions to execute + + + + Executes all actions in parallel + Returns when the first one completes + + Actions to execute + + + + Executes actions in sequence asynchronously. + Returns immediately. + + A state context that passes + Actions to execute in the order they should run + + + + Executes actions in sequence asynchronously. + Returns immediately. + + + Actions to execute in the order they should run + + + + An event to call after a thread is created, but before + it's first use. + + + + + An event to call when a thread is about to exit, after + it is no longer belong to the pool. + + + + + A reference to the current work item a thread from the thread pool + is executing. + + + + + This event is fired when a thread is created. + Use it to initialize a thread before the work items use it. + + + + + This event is fired when a thread is terminating. + Use it for cleanup. + + + + + Get/Set the lower limit of threads in the pool. + + + + + Get/Set the upper limit of threads in the pool. + + + + + Get the number of threads in the thread pool. + Should be between the lower and the upper limits. + + + + + Get the number of busy (not idle) threads in the thread pool. + + + + + Returns true if the current running work item has been cancelled. + Must be used within the work item's callback method. + The work item should sample this value in order to know if it + needs to quit before its completion. + + + + + Thread Pool start information (readonly) + + + + + Return the local calculated performance counters + Available only if STPStartInfo.EnableLocalPerformanceCounters is true. + + + + + Get/Set the maximum number of work items that execute cocurrency on the thread pool + + + + + Get the number of work items in the queue. + + + + + WorkItemsGroup start information (readonly) + + + + + This event is fired when all work items are completed. + (When IsIdle changes to true) + This event only work on WorkItemsGroup. On SmartThreadPool + it throws the NotImplementedException. + + + + + The thread creation time + The value is stored as UTC value. + + + + + The last time this thread has been running + It is updated by IAmAlive() method + The value is stored as UTC value. + + + + + A reference from each thread in the thread pool to its SmartThreadPool + object container. + With this variable a thread can know whatever it belongs to a + SmartThreadPool. + + + + + A reference to the current work item a thread from the thread pool + is executing. + + + + + Summary description for STPPerformanceCounter. + + + + + Summary description for STPStartInfo. + + + + + Summary description for WIGStartInfo. + + + + + Get a readonly version of this WIGStartInfo + + Returns a readonly reference to this WIGStartInfoRO + + + + Get/Set if to use the caller's security context + + + + + Get/Set if to use the caller's HTTP context + + + + + Get/Set if to dispose of the state object of a work item + + + + + Get/Set the run the post execute options + + + + + Get/Set the default post execute callback + + + + + Get/Set if the work items execution should be suspended until the Start() + method is called. + + + + + Get/Set the default priority that a work item gets when it is enqueued + + + + + Get/Set the if QueueWorkItem of Action<...>/Func<...> fill the + arguments as an object array into the state of the work item. + The arguments can be access later by IWorkItemResult.State. + + + + + Get a readonly version of this STPStartInfo. + + Returns a readonly reference to this STPStartInfo + + + + Get/Set the idle timeout in milliseconds. + If a thread is idle (starved) longer than IdleTimeout then it may quit. + + + + + Get/Set the lower limit of threads in the pool. + + + + + Get/Set the upper limit of threads in the pool. + + + + + Get/Set the scheduling priority of the threads in the pool. + The Os handles the scheduling. + + + + + Get/Set the thread pool name. Threads will get names depending on this. + + + + + Get/Set the performance counter instance name of this SmartThreadPool + The default is null which indicate not to use performance counters at all. + + + + + Enable/Disable the local performance counter. + This enables the user to get some performance information about the SmartThreadPool + without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.) + The default is false. + + + + + Get/Set backgroundness of thread in thread pool. + + + + + Get/Set the apartment state of threads in the thread pool + + + + + Get/Set the max stack size of threads in the thread pool + + + + + Holds a callback delegate and the state for that delegate. + + + + + Callback delegate for the callback. + + + + + State with which to call the callback delegate. + + + + + Stores the caller's context + + + + + Holds the result of the mehtod + + + + + Hold the exception if the method threw it + + + + + Hold the state of the work item + + + + + A ManualResetEvent to indicate that the result is ready + + + + + A reference count to the _workItemCompleted. + When it reaches to zero _workItemCompleted is Closed + + + + + Represents the result state of the work item + + + + + Work item info + + + + + A reference to an object that indicates whatever the + WorkItemsGroup has been canceled + + + + + A reference to an object that indicates whatever the + SmartThreadPool has been canceled + + + + + The work item group this work item belong to. + + + + + The thread that executes this workitem. + This field is available for the period when the work item is executed, before and after it is null. + + + + + The absulote time when the work item will be timeout + + + + + Stores how long the work item waited on the stp queue + + + + + Stores how much time it took the work item to execute after it went out of the queue + + + + + Initialize the callback holding object. + + The workItemGroup of the workitem + The WorkItemInfo of te workitem + Callback delegate for the callback. + State with which to call the callback delegate. + + We assume that the WorkItem object is created within the thread + that meant to run the callback + + + + Change the state of the work item to in progress if it wasn't canceled. + + + Return true on success or false in case the work item was canceled. + If the work item needs to run a post execute then the method will return true. + + + + + Execute the work item and the post execute + + + + + Execute the work item + + + + + Runs the post execute callback + + + + + Set the result of the work item to return + + The result of the work item + The exception that was throw while the workitem executed, null + if there was no exception. + + + + Returns the work item result + + The work item result + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + true when every work item in waitableResults has completed; otherwise false. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Fill an array of wait handles with the work items wait handles. + + An array of work item results + An array of wait handles to fill + + + + Release the work items' wait handles + + An array of work item results + + + + Sets the work item's state + + The state to set the work item to + + + + Signals that work item has been completed or canceled + + Indicates that the work item has been canceled + + + + Cancel the work item if it didn't start running yet. + + Returns true on success or false if the work item is in progress or already completed + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits for the result, timeout, or cancel. + In case of error the method throws and exception + + The result of the work item + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits for the result, timeout, or cancel. + In case of error the e argument is filled with the exception + + The result of the work item + + + + A wait handle to wait for completion, cancel, or timeout + + + + + Called when the WorkItem starts + + + + + Called when the WorkItem completes + + + + + Returns true when the work item has completed or canceled + + + + + Returns true when the work item has canceled + + + + + Returns the priority of the work item + + + + + Indicates the state of the work item in the thread pool + + + + + A back reference to the work item + + + + + Return the result, same as GetResult() + + + + + Returns the exception if occured otherwise returns null. + This value is valid only after the work item completed, + before that it is always null. + + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + A callback to execute + Returns a work item + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + A callback to execute + The priority of the work item + Returns a work item + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + Work item info + A callback to execute + Returns a work item + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + The work item priority + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + Work item information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + The work item priority + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + The work item priority + Returns a work item + + + + Summary description for WorkItemInfo. + + + + + Get/Set if to use the caller's security context + + + + + Get/Set if to use the caller's HTTP context + + + + + Get/Set if to dispose of the state object of a work item + + + + + Get/Set the run the post execute options + + + + + Get/Set the post execute callback + + + + + Get/Set the work item's priority + + + + + Get/Set the work item's timout in milliseconds. + This is a passive timout. When the timout expires the work item won't be actively aborted! + + + + + Summary description for WorkItemsGroup. + + + + + A reference to the SmartThreadPool instance that created this + WorkItemsGroup. + + + + + A flag to indicate if the Work Items Group is now suspended. + + + + + Defines how many work items of this WorkItemsGroup can run at once. + + + + + Priority queue to hold work items before they are passed + to the SmartThreadPool. + + + + + Indicate how many work items are waiting in the SmartThreadPool + queue. + This value is used to apply the concurrency. + + + + + Indicate how many work items are currently running in the SmartThreadPool. + This value is used with the Cancel, to calculate if we can send new + work items to the STP. + + + + + WorkItemsGroup start information + + + + + Signaled when all of the WorkItemsGroup's work item completed. + + + + + A common object for all the work items that this work items group + generate so we can mark them to cancel in O(1) + + + + + Start the Work Items Group if it was started suspended + + + + + Wait for the thread pool to be idle + + + + + The OnIdle event + + + + + WorkItemsGroup start information + + + + + WorkItemsQueue class. + + + + + Waiters queue (implemented as stack). + + + + + Waiters count + + + + + Work items queue + + + + + Indicate that work items are allowed to be queued + + + + + A flag that indicates if the WorkItemsQueue has been disposed. + + + + + Enqueue a work item to the queue. + + + + + Waits for a work item or exits on timeout or cancel + + Timeout in milliseconds + Cancel wait handle + Returns true if the resource was granted + + + + Cleanup the work items queue, hence no more work + items are allowed to be queue + + + + + Returns the WaiterEntry of the current thread + + + In order to avoid creation and destuction of WaiterEntry + objects each thread has its own WaiterEntry object. + + + + Push a new waiter into the waiter's stack + + A waiter to put in the stack + + + + Pop a waiter from the waiter's stack + + Returns the first waiter in the stack + + + + Remove a waiter from the stack + + A waiter entry to remove + If true the waiter count is always decremented + + + + Each thread in the thread pool keeps its own waiter entry. + + + + + Returns the current number of work items in the queue + + + + + Returns the current number of waiters + + + + + Event to signal the waiter that it got the work item. + + + + + Flag to know if this waiter already quited from the queue + because of a timeout. + + + + + Flag to know if the waiter was signaled and got a work item. + + + + + A work item that passed directly to the waiter withou going + through the queue + + + + + Signal the waiter that it got a work item. + + Return true on success + The method fails if Timeout() preceded its call + + + + Mark the wait entry that it has been timed out + + Return true on success + The method fails if Signal() preceded its call + + + + Reset the wait entry so it can be used again + + + + + Free resources + + + + + Respond with a 'Soft redirect' so smart clients (e.g. ajax) have access to the response and + can decide whether or not they should redirect + + + + + Decorate the response with an additional client-side event to instruct participating + smart clients (e.g. ajax) with hints to transparently invoke client-side functionality + + + + + Shortcut to get the ResponseDTO whether it's bare or inside a IHttpResult + + + + + + + Alias of AsDto + + + + + Shortcut to get the ResponseDTO whether it's bare or inside a IHttpResult + + + TResponse if found; otherwise null + + + + Alias of AsDto + + + + + Whether the response is an IHttpError or Exception + + + + + rangeHeader should be of the format "bytes=0-" or "bytes=0-12345" or "bytes=123-456" + + + + + Adds 206 PartialContent Status, Content-Range and Content-Length headers + + + + + Writes partial range as specified by start-end, from fromStream to toStream. + + + + + Service error logs are kept in 'urn:ServiceErrors:{ServiceName}' + + + + + Combined service error logs are maintained in 'urn:ServiceErrors:All' + + + + + RequestLogs service Route, default is /requestlogs + + + + + Turn On/Off Session Tracking + + + + + Turn On/Off Logging of Raw Request Body, default is Off + + + + + Turn On/Off Tracking of Responses + + + + + Turn On/Off Tracking of Exceptions + + + + + Size of InMemoryRollingRequestLogger circular buffer + + + + + Limit access to /requestlogs service to these roles + + + + + Change the RequestLogger provider. Default is InMemoryRollingRequestLogger + + + + + Don't log requests of these types. By default RequestLog's are excluded + + + + + Don't log request bodys for services with sensitive information. + By default Auth and Registration requests are hidden. + + + + + Generic + Useful IService base class + + + + + Resolve an alternate Web Service from ServiceStack's IOC container. + + + + + + + Dynamic Session Bag + + + + + Typed UserSession + + + + + Indicates that the request dto, which is associated with this attribute, + requires authentication. + + + + + Restrict authentication to a specific . + For example, if this attribute should only permit access + if the user is authenticated with , + you should set this property to . + + + + + Redirect the client to a specific URL if authentication failed. + If this property is null, simply `401 Unauthorized` is returned. + + + + + Enable the authentication feature and configure the AuthService. + + + + + Inject logic into existing services by introspecting the request and injecting your own + validation logic. Exceptions thrown will have the same behaviour as if the service threw it. + + If a non-null object is returned the request will short-circuit and return that response. + + The instance of the service + GET,POST,PUT,DELETE + + Response DTO; non-null will short-circuit execution and return that response + + + + Public API entry point to authenticate via code + + + null; if already autenticated otherwise a populated instance of AuthResponse + + + + The specified may change as a side-effect of this method. If + subsequent code relies on current data be sure to reload + the session istance via . + + + + + Remove the Users Session + + + + + + + + The entry point for all AuthProvider providers. Runs inside the AuthService so exceptions are treated normally. + Overridable so you can provide your own Auth implementation. + + + + + Determine if the current session is already authenticated with this AuthProvider + + + + + Allows specifying a global fallback config that if exists is formatted with the Provider as the first arg. + E.g. this appSetting with the TwitterAuthProvider: + oauth.CallbackUrl="http://localhost:11001/auth/{0}" + Would result in: + oauth.CallbackUrl="http://localhost:11001/auth/twitter" + + + + + + Remove the Users Session + + + + + + + + Saves the Auth Tokens for this request. Called in OnAuthenticated(). + Overrideable, the default behaviour is to call IUserAuthRepository.CreateOrMergeAuthSession(). + + + + + Base class for entity validator classes. + + The type of the object being validated + + + + Defines a validator for a particualr type. + + + + + + Defines a validator for a particular type. + + + + + Validates the specified instance + + + A ValidationResult containing any validation failures + + + + Validates the specified instance. + + A ValidationContext + A ValidationResult object containy any validation failures. + + + + Creates a hook to access various meta data properties + + A IValidatorDescriptor object which contains methods to access metadata + + + + Checks to see whether the validator can validate objects of the specified type + + + + + Validates the specified instance. + + The instance to validate + A ValidationResult object containing any validation failures. + + + + Sets the cascade mode for all rules within this validator. + + + + + Validates the specified instance + + The object to validate + A ValidationResult object containing any validation failures + + + + Validates the specified instance. + + Validation Context + A ValidationResult object containing any validation failures. + + + + Adds a rule to the current validator. + + + + + + Creates a that can be used to obtain metadata about the current validator. + + + + + Defines a validation rule for a specify property. + + + RuleFor(x => x.Surname)... + + The type of property being validated + The expression representing the property to validate + an IRuleBuilder instance on which validators can be defined + + + + Defines a custom validation rule using a lambda expression. + If the validation rule fails, it should return a instance of a ValidationFailure + If the validation rule succeeds, it should return null. + + A lambda that executes custom validation rules. + + + + Defines a custom validation rule using a lambda expression. + If the validation rule fails, it should return an instance of ValidationFailure + If the validation rule succeeds, it should return null. + + A lambda that executes custom validation rules + + + + Defines a RuleSet that can be used to group together several validators. + + The name of the ruleset. + Action that encapsulates the rules in the ruleset. + + + + Defines a RuleSet that can be used to provide specific validation rules for specific HTTP methods (GET, POST...) + + The HTTP methods where this rule set should be used. + Action that encapuslates the rules in the ruleset. + + + + Defines a condition that applies to several rules + + The condition that should apply to multiple rules + Action that encapsulates the rules. + + + + + Defiles an inverse condition that applies to several rules + + The condition that should be applied to multiple rules + Action that encapsulates the rules + + + + Returns an enumerator that iterates through the collection of validation rules. + + + A that can be used to iterate through the collection. + + 1 + + + + Sets the cascade mode for all rules within this validator. + + + + + Create a Facebook App at: https://developers.facebook.com/apps + The Callback URL for your app should match the CallbackUrl provided. + + + + + The entry point for all AuthProvider providers. Runs inside the AuthService so exceptions are treated normally. + Overridable so you can provide your own Auth implementation. + + + + + + + + + Sets the CallbackUrl and session.ReferrerUrl if not set and initializes the session tokens for this AuthProvider + + + + + + + + + Download Yammer User Info given its ID. + + + The Yammer User ID. + + + The User info in JSON format. + + + + Yammer provides a method to retrieve current user information via + "https://www.yammer.com/api/v1/users/current.json". + + + However, to ensure consistency with the rest of the Auth codebase, + the explicit URL will be used, where [:id] denotes the User ID: + "https://www.yammer.com/api/v1/users/[:id].json" + + + Refer to: https://developer.yammer.com/restapi/ for full documentation. + + + + + + Thread-safe In memory UserAuth data store so it can be used without a dependency on Redis. + + + + + Creates the required missing tables or DB schema + + + + + Create new Registration + + + + + Logic to update UserAuth from Registration info, not enabled on OnPut because of security. + + + + + Thank you Martijn + http://www.dijksterhuis.org/creating-salted-hash-values-in-c/ + + + + + Create an app at https://dev.twitter.com/apps to get your ConsumerKey and ConsumerSecret for your app. + The Callback URL for your app should match the CallbackUrl provided. + + + + + The ServiceStack Yammer OAuth provider. + + + + This provider is loosely based on the existing ServiceStack's Facebook OAuth provider. + + + For the full info on Yammer's OAuth2 authentication flow, refer to: + https://developer.yammer.com/authentication/#a-oauth2 + + + Note: Add these to your application / web config settings under appSettings and replace + values as appropriate. + + + + + + + + + ]]> + + + + + + The OAuth provider name / identifier. + + + + + Initializes a new instance of the class. + + + The application settings (in web.config). + + + + + Authenticate against Yammer OAuth endpoint. + + + The auth service. + + + The session. + + + The request. + + + The . + + + + + Load the UserAuth info into the session. + + + The User session. + + + The OAuth tokens. + + + The auth info. + + + + + Load the UserOAuth info into the session. + + + The auth session. + + + The OAuth tokens. + + + + + Gets or sets the Yammer OAuth client id. + + + + + Gets or sets the Yammer OAuth client secret. + + + + + Gets or sets the Yammer OAuth pre-auth url. + + + + + The Yammer User's email addresses. + + + + + Gets or sets the email address type (e.g. primary). + + + + + Gets or sets the email address. + + + + + Removes items from cache that have keys matching the specified wildcard pattern + + Cache client + The wildcard, where "*" means any sequence of characters and "?" means any single character. + + + + Removes items from the cache based on the specified regular expression pattern + + Cache client + Regular expression pattern to search cache keys + + + + Add value with specified key to the cache, and set the cache entry to never expire. + + + + + Stores The value with key only if such key doesn't exist at the server yet. + + + + + Adds or replaces the value with key, and sets the cache entry to never expire. + + + + + Adds or replaces the value with key. + + + + + Adds or replaces the value with key. + + + + + Replace the value with specified key if it exists, and set the cache entry to never expire. + + + + + Replace the value with specified key if it exists. + + + + + Add the value with key to the cache, set to never expire. + + + + + Add or replace the value with key to the cache, set to never expire. + + + + + Replace the value with key in the cache, set to never expire. + + + + + Add the value with key to the cache, set to expire at specified DateTime. + + This method examines the DateTimeKind of expiresAt to determine if conversion to + universal time is needed. The version of Add that takes a TimeSpan expiration is faster + than using this method with a DateTime of Kind other than Utc, and is not affected by + ambiguous local time during daylight savings/standard time transition. + + + + Add or replace the value with key to the cache, set to expire at specified DateTime. + + This method examines the DateTimeKind of expiresAt to determine if conversion to + universal time is needed. The version of Set that takes a TimeSpan expiration is faster + than using this method with a DateTime of Kind other than Utc, and is not affected by + ambiguous local time during daylight savings/standard time transition. + + + + Replace the value with key in the cache, set to expire at specified DateTime. + + This method examines the DateTimeKind of expiresAt to determine if conversion to + universal time is needed. The version of Replace that takes a TimeSpan expiration is faster + than using this method with a DateTime of Kind other than Utc, and is not affected by + ambiguous local time during daylight savings/standard time transition. + + + + Add the value with key to the cache, set to expire after specified TimeSpan. + + + + + Add or replace the value with key to the cache, set to expire after specified TimeSpan. + + + + + Replace the value with key in the cache, set to expire after specified TimeSpan. + + + + + Create new instance of CacheEntry. + + + + UTC time at which CacheEntry expires. + + + + Would've preferred to use [assembly: ContractNamespace] attribute but it is not supported in Mono + + + + + More familiar name for the new crowd. + + + + + The tier lets you specify a retrieving a setting with the tier prefix first before falling back to the original key. + E.g a tier of 'Live' looks for 'Live.{Key}' or if not found falls back to '{Key}'. + + + + + Returns string if exists, otherwise null + + + + + + + Provides a common interface for Settings providers such as + ConfigurationManager or Azure's RoleEnvironment. The only + requirement is that if the implementation cannot find the + specified key, the return value must be null + + The key for the setting + The string value of the specified key, or null if the key + was invalid + + + + Gets the nullable app setting. + + + + + Gets the app setting. + + + + + Determines wheter the Config section identified by the sectionName exists. + + + + + Returns AppSetting[key] if exists otherwise defaultValue + + + + + Returns AppSetting[key] if exists otherwise defaultValue, for non-string values + + + + + Gets the connection string setting. + + + + + Gets the connection string. + + + + + Gets the list from app setting. + + + + + Gets the dictionary from app setting. + + + + + Get the static Parse(string) method on the type supplied + + + + + Gets the constructor info for T(string) if exists. + + + + + Returns the value returned by the 'T.Parse(string)' method if exists otherwise 'new T(string)'. + e.g. if T was a TimeSpan it will return TimeSpan.Parse(textValue). + If there is no Parse Method it will attempt to create a new instance of the destined type + + + + + Plugin adds support for Cross-origin resource sharing (CORS, see http://www.w3.org/TR/access-control/). + CORS allows to access resources from different domain which usually forbidden by origin policy. + + + + + Represents a default constructor with Allow Origin equals to "*", Allowed GET, POST, PUT, DELETE, OPTIONS request and allowed "Content-Type" header. + + + + + Attribute marks that specific response class has support for Cross-origin resource sharing (CORS, see http://www.w3.org/TR/access-control/). CORS allows to access resources from different domain which usually forbidden by origin policy. + + + + + Represents a default constructor with Allow Origin equals to "*", Allowed GET, POST, PUT, DELETE, OPTIONS request and allowed "Content-Type" header. + + + + + Change the default HTML view or template used for the HTML response of this service + + + + + Class that can be used to find all the validators from a collection of types. + + + + + Creates a scanner that works on a sequence of types. + + + + + Finds all the validators in the specified assembly. + + + + + Finds all the validators in the assembly containing the specified type. + + + + + Performs the specified action to all of the assembly scan results. + + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + 1 + + + + Result of performing a scan. + + + + + Creates an instance of an AssemblyScanResult. + + + + + Validator interface type, eg IValidator<Foo> + + + + + Concrete type that implements the InterfaceType, eg FooValidator. + + + + + Implementation of IValidatorFactory that looks for ValidatorAttribute instances on the specified type in order to provide the validator instance. + + + + + Gets validators for a particular type. + + + + + Gets the validator for the specified type. + + + + + Gets the validator for the specified type. + + + + + Gets a validator for the appropriate type. + + + + + Gets a validator for the appropriate type. + + + + + Validator attribute to define the class that will describe the Validation rules + + + + + Creates an instance of the ValidatorAttribute allowing a validator type to be specified. + + + + + The type of the validator used to validate the current type. + + + + + Associates an instance of IValidator with the current property rule and is used to validate each item within the collection. + + The validator to use + + + + Rule builder + + + + + + + Rule builder + + + + + + + Associates a validator with this the property for this rule builder. + + The validator to set + + + + + Associates an instance of IValidator with the current property rule. + + The validator to use + + + + Represents an object that is configurable. + + Type of object being configured + Return type + + + + Configures the current object. + + Action to configure the object. + + + + + Extension methods that provide the default set of validators. + + + + + Defines a 'not null' validator on the current rule builder. + Validation will fail if the property is null. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + + + + + Defines a 'not empty' validator on the current rule builder. + Validation will fail if the property is null, an empty or the default value for the type (for example, 0 for integers) + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + + + + + Defines a length validator on the current rule builder, but only for string properties. + Validation will fail if the length of the string is outside of the specifed range. The range is inclusive. + + Type of object being validated + The rule builder on which the validator should be defined + + + + + Defines a length validator on the current rule builder, but only for string properties. + Validation will fail if the length of the string is not equal to the length specified. + + Type of object being validated + The rule builder on which the validator should be defined + + + + + Defines a regular expression validator on the current rule builder, but only for string properties. + Validation will fail if the value returned by the lambda does not match the regular expression. + + Type of object being validated + The rule builder on which the validator should be defined + The regular expression to check the value against. + + + + + Defines a regular expression validator on the current rule builder, but only for string properties. + Validation will fail if the value returned by the lambda is not a valid email address. + + Type of object being validated + The rule builder on which the validator should be defined + + + + + Defines a 'not equal' validator on the current rule builder. + Validation will fail if the specified value is equal to the value of the property. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value to compare + Equality comparer to use + + + + + Defines a 'not equal' validator on the current rule builder using a lambda to specify the value. + Validation will fail if the value returned by the lambda is equal to the value of the property. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression to provide the comparison value + Equality Comparer to use + + + + + Defines an 'equals' validator on the current rule builder. + Validation will fail if the specified value is not equal to the value of the property. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value to compare + Equality Comparer to use + + + + + Defines an 'equals' validator on the current rule builder using a lambda to specify the comparison value. + Validation will fail if the value returned by the lambda is not equal to the value of the property. + + The type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression to provide the comparison value + Equality comparer to use + + + + + Defines a predicate validator on the current rule builder using a lambda expression to specify the predicate. + Validation will fail if the specified lambda returns false. + Validation will succeed if the specifed lambda returns true. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression specifying the predicate + + + + + Defines a predicate validator on the current rule builder using a lambda expression to specify the predicate. + Validation will fail if the specified lambda returns false. + Validation will succeed if the specifed lambda returns true. + This overload accepts the object being validated in addition to the property being validated. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression specifying the predicate + + + + + Defines a predicate validator on the current rule builder using a lambda expression to specify the predicate. + Validation will fail if the specified lambda returns false. + Validation will succeed if the specifed lambda returns true. + This overload accepts the object being validated in addition to the property being validated. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression specifying the predicate + + + + + Defines a 'less than' validator on the current rule builder. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than' validator on the current rule builder. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than' validator on the current rule builder. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than or equal' validator on the current rule builder. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than or equal' validator on the current rule builder. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda that should return the value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda that should return the value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Validates certain properties of the specified instance. + + The current validator + The object to validate + Expressions to specify the properties to validate + A ValidationResult object containing any validation failures + + + + Validates certain properties of the specified instance. + + The object to validate + The names of the properties to validate. + A ValidationResult object containing any validation failures. + + + + Performs validation and then throws an exception if validation fails. + + + + + Defines an 'inclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is inclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines an 'inclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is inclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines an 'exclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is exclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines an 'exclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is exclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines a credit card validator for the current rule builder that ensures that the specified string is a valid credit card number. + + + + + Default options that can be used to configure a validator. + + + + + Specifies the cascade mode for failures. + If set to 'Stop' then execution of the rule will stop once the first validator in the chain fails. + If set to 'Continue' then all validators in the chain will execute regardless of failures. + + + + + Specifies a custom action to be invoked when the validator fails. + + + + + + + + + + Specifies a custom error message to use if validation fails. + + The current rule + The error message to use + + + + + Specifies a custom error message to use if validation fails. + + The current rule + The error message to use + Additional arguments to be specified when formatting the custom error message. + + + + + Specifies a custom error message to use if validation fails. + + The current rule + The error message to use + Additional property values to be included when formatting the custom error message. + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + Custom message format args + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + Custom message format args + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + The resource accessor builder to use. + + + + + Specifies a custom error code to use when validation fails + + The current rule + The error code to use + + + + + Specifies a condition limiting when the validator should run. + The validator will only be executed if the result of the lambda returns true. + + The current rule + A lambda expression that specifies a condition for when the validator should run + Whether the condition should be applied to the current rule or all rules in the chain + + + + + Specifies a condition limiting when the validator should not run. + The validator will only be executed if the result of the lambda returns false. + + The current rule + A lambda expression that specifies a condition for when the validator should not run + Whether the condition should be applied to the current rule or all rules in the chain + + + + + Specifies a custom property name to use within the error message. + + The current rule + The property name to use + + + + + Specifies a localized name for the error message. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + Resource accessor builder to use + + + + Overrides the name of the property associated with this rule. + NOTE: This is a considered to be an advanced feature. 99% of the time that you use this, you actually meant to use WithName. + + The current rule + The property name to use + + + + + Specifies custom state that should be stored alongside the validation message when validation fails for this rule. + + + + + + + + + + Specifies how rules should cascade when one fails. + + + + + When a rule fails, execution continues to the next rule. + + + + + When a rule fails, validation is stopped and all other rules in the chain will not be executed. + + + + + Specifies where a When/Unless condition should be applied + + + + + Applies the condition to all validators declared so far in the chain. + + + + + Applies the condition to the current validator only. + + + + + Validator implementation that allows rules to be defined without inheriting from AbstractValidator. + + + + public class Customer { + public int Id { get; set; } + public string Name { get; set; } + + public static readonly InlineValidator<Customer> Validator = new InlineValidator<Customer> { + v => v.RuleFor(x => x.Name).NotNull(), + v => v.RuleFor(x => x.Id).NotEqual(0), + } + } + + + + + + + Allows configuration of the validator. + + + + + Delegate that specifies configuring an InlineValidator. + + + + + Default validator selector that will execute all rules that do not belong to a RuleSet. + + + + + Determines whether or not a rule should execute. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Custom IValidationRule for performing custom logic. + + + + + + Defines a rule associated with a property which can have multiple validators. + + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + The validators that are grouped under this rule. + + + + + Name of the rule-set to which this rule belongs. + + + + + Creates a new DelegateValidator using the specified function to perform validation. + + + + + Creates a new DelegateValidator using the specified function to perform validation. + + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + Rule set to which this rule belongs. + + + + + The validators that are grouped under this rule. + + + + + Useful extensions + + + + + Gets a MemberInfo from a member expression. + + + + + Gets a MemberInfo from a member expression. + + + + + Splits pascal case, so "FooBar" would become "Foo Bar" + + + + + Helper method to construct a constant expression from a constant. + + Type of object being validated + Type of property being validated + The value being compared + + + + + Based on a child validator and a propery rule, infers whether the validator should be wrapped in a ChildValidatorAdaptor or a CollectionValidatorAdaptor + + + + + Instancace cache. + TODO: This isn't actually completely thread safe. It would be much better to use ConcurrentDictionary, but this isn't available in Silverlight/WP7. + + + + + Gets or creates an instance using Activator.CreateInstance + + The type to instantiate + The instantiated object + + + + Gets or creates an instance using a custom factory + + The type to instantiate + The custom factory + The instantiated object + + + + Selects validators that are associated with a particular property. + + + + + Creates a new instance of MemberNameValidatorSelector. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Creates a MemberNameValidatorSelector from a collection of expressions. + + + + + Assists in the construction of validation messages. + + + + + Default Property Name placeholder. + + + + + Adds a value for a validation message placeholder. + + + + + + + + Appends a property name to the message. + + The name of the property + + + + + Adds additional arguments to the message for use with standard string placeholders. + + Additional arguments + + + + + Constructs the final message from the specified template. + + Message template + The message with placeholders replaced with their appropriate values + + + + Represents a chain of properties + + + + + Creates a new PropertyChain. + + + + + Creates a new PropertyChain based on another. + + + + + Adds a MemberInfo instance to the chain + + Member to add + + + + Adds a property name to the chain + + Name of the property to add + + + + Adds an indexer to the property chain. For example, if the following chain has been constructed: + Parent.Child + then calling AddIndexer(0) would convert this to: + Parent.Child[0] + + + + + + Creates a string representation of a property chain. + + + + + Checks if the current chain is the child of another chain. + For example, if chain1 were for "Parent.Child" and chain2 were for "Parent.Child.GrandChild" then + chain2.IsChildChainOf(chain1) would be true. + + The parent chain to compare + True if the current chain is the child of the other chain, otherwise false + + + + Builds a property path. + + + + + Defines a rule associated with a property. + + + + + Creates a new property rule. + + Property + Function to get the property value + Lambda expression used to create the rule + Function to get the cascade mode. + Type to validate + Container type that owns the property + + + + Creates a new property rule from a lambda expression. + + + + + Creates a new property rule from a lambda expression. + + + + + Adds a validator to the rule. + + + + + Replaces a validator in this rule. Used to wrap validators. + + + + + Display name for the property. + + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + Invokes a property validator using the specified validation context. + + + + + Property associated with this rule. + + + + + Function that can be invoked to retrieve the value of the property. + + + + + Expression that was used to create the rule. + + + + + String source that can be used to retrieve the display name (if null, falls back to the property name) + + + + + Rule set that this rule belongs to (if specified) + + + + + Function that will be invoked if any of the validators associated with this rule fail. + + + + + The current validator being configured by this rule. + + + + + Type of the property being validated + + + + + Cascade mode for this rule. + + + + + Validators associated with this rule. + + + + + Returns the property name for the property being validated. + Returns null if it is not a property being validated (eg a method call) + + + + + Builds a validation rule and constructs a validator. + + Type of object being validated + Type of property being validated + + + + Rule builder that starts the chain + + + + + + + Creates a new instance of the RuleBuilder class. + + + + + Sets the validator associated with the rule. + + The validator to set + + + + + Sets the validator associated with the rule. Use with complex properties where an IValidator instance is already declared for the property type. + + The validator to set + + + + The rule being created by this RuleBuilder. + + + + + Selects validators that belong to the specified rulesets. + + + + + Creates a new instance of the RulesetValidatorSelector. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Provides metadata about a validator. + + + + + Gets the name display name for a property. + + + + + Gets a collection of validators grouped by property. + + + + + Gets validators for a particular property. + + + + + Gets rules for a property. + + + + + Builds a delegate for retrieving a localised resource from a resource type and property name. + + + + + Gets a function that can be used to retrieve a message from a resource type and resource name. + + + + + Builds a delegate for retrieving a localised resource from a resource type and property name. + + + + + Builds a function used to retrieve the resource. + + + + + Gets the PropertyInfo for a resource. + ResourceType and ResourceName are ref parameters to allow derived types + to replace the type/name of the resource before the delegate is constructed. + + + + + Implemenetation of IResourceAccessorBuilder that can fall back to the default resource provider. + + + + + Gets the PropertyInfo for a resource. + ResourceType and ResourceName are ref parameters to allow derived types + to replace the type/name of the resource before the delegate is constructed. + + + + + Provides error message templates + + + + + Construct the error message template + + Error message template + + + + The name of the resource if localized. + + + + + The type of the resource provider if localized. + + + + + Represents a localized string. + + + + + Creates a new instance of the LocalizedErrorMessageSource class using the specified resource name and resource type. + + The resource type + The resource name + Strategy used to construct the resource accessor + + + + Creates an IErrorMessageSource from an expression: () => MyResources.SomeResourceName + + The expression + Strategy used to construct the resource accessor + Error message source + + + + Construct the error message template + + Error message template + + + + The name of the resource if localized. + + + + + The type of the resource provider if localized. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to '{PropertyName}' is not a valid credit card number.. + + + + + Looks up a localized string similar to '{PropertyName}' is not a valid email address.. + + + + + Looks up a localized string similar to '{PropertyName}' should be equal to '{PropertyValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be {MaxLength} characters in length. You entered {TotalLength} characters.. + + + + + Looks up a localized string similar to '{PropertyName}' must be between {From} and {To} (exclusive). You entered {Value}.. + + + + + Looks up a localized string similar to '{PropertyName}' must be greater than '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be greater than or equal to '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be between {From} and {To}. You entered {Value}.. + + + + + Looks up a localized string similar to '{PropertyName}' must be between {MinLength} and {MaxLength} characters. You entered {TotalLength} characters.. + + + + + Looks up a localized string similar to '{PropertyName}' must be less than '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be less than or equal to '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' should not be empty.. + + + + + Looks up a localized string similar to '{PropertyName}' should not be equal to '{PropertyValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must not be empty.. + + + + + Looks up a localized string similar to The specified condition was not met for '{PropertyName}'.. + + + + + Looks up a localized string similar to '{PropertyName}' is not in the correct format.. + + + + + Represents a static string. + + + + + Creates a new StringErrorMessageSource using the specified error message as the error template. + + The error message template. + + + + Construct the error message template + + Error message template + + + + The name of the resource if localized. + + + + + The type of the resource provider if localized. + + + + + Creates a new validation failure. + + + + + Creates a new ValidationFailure. + + + + + Creates a textual representation of the failure. + + + + + The name of the property. + + + + + The error message + + + + + The error code + + + + + The property value that caused the failure. + + + + + Custom state associated with the failure. + + + + + Used for providing metadata about a validator. + + + + + A custom property validator. + This interface should not be implemented directly in your code as it is subject to change. + Please inherit from PropertyValidator instead. + + + + + Creates an error validation result for this validator. + + The validator context + Returns an error validation result. + + + + Ensures that the property value is a valid credit card number. + + + + + Provides access to the anti-forgery system, which provides protection against + Cross-site Request Forgery (XSRF, also called CSRF) attacks. + + + + + Generates an anti-forgery token for this request. This token can + be validated by calling the Validate() method. + + An HTML string corresponding to an <input type="hidden"> + element. This element should be put inside a <form>. + + This method has a side effect: it may set a response cookie. + + + + + Generates an anti-forgery token pair (cookie and form token) for this request. + This method is similar to GetHtml(), but this method gives the caller control + over how to persist the returned values. To validate these tokens, call the + appropriate overload of Validate. + + The anti-forgery token - if any - that already existed + for this request. May be null. The anti-forgery system will try to reuse this cookie + value when generating a matching form token. + Will contain a new cookie value if the old cookie token + was null or invalid. If this value is non-null when the method completes, the caller + must persist this value in the form of a response cookie, and the existing cookie value + should be discarded. If this value is null when the method completes, the existing + cookie value was valid and needn't be modified. + The value that should be stored in the <form>. The caller + should take care not to accidentally swap the cookie and form tokens. + + Unlike the GetHtml() method, this method has no side effect. The caller + is responsible for setting the response cookie and injecting the returned + form token as appropriate. + + + + + Validates an anti-forgery token that was supplied for this request. + The anti-forgery token may be generated by calling GetHtml(). + + + Throws an HttpAntiForgeryException if validation fails. + + + + + Validates an anti-forgery token pair that was generated by the GetTokens method. + + The token that was supplied in the request cookie. + The token that was supplied in the request form body. + + Throws an HttpAntiForgeryException if validation fails. + + + + + Provides programmatic configuration for the anti-forgery token system. + + + + + Specifies an object that can provide additional data to put into all + generated tokens and that can validate additional data in incoming + tokens. + + + + + Specifies the name of the cookie that is used by the anti-forgery + system. + + + If an explicit name is not provided, the system will automatically + generate a name. + + + + + Specifies whether SSL is required for the anti-forgery system + to operate. If this setting is 'true' and a non-SSL request + comes into the system, all anti-forgery APIs will fail. + + + + + Specifies whether the anti-forgery system should skip checking + for conditions that might indicate misuse of the system. Please + use caution when setting this switch, as improper use could open + security holes in the application. + + + Setting this switch will disable several checks, including: + - Identity.IsAuthenticated = true without Identity.Name being set + - special-casing claims-based identities + + + + + If claims-based authorization is in use, specifies the claim + type from the identity that is used to uniquely identify the + user. If this property is set, all claims-based identities + must return unique values for this claim type. + + + If claims-based authorization is in use and this property has + not been set, the anti-forgery system will automatically look + for claim types "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" + and "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider". + + + + + Allows providing or validating additional custom data for anti-forgery tokens. + For example, the developer could use this to supply a nonce when the token is + generated, then he could validate the nonce when the token is validated. + + + The anti-forgery system already embeds the client's username within the + generated tokens. This interface provides and consumes supplemental + data. If an incoming anti-forgery token contains supplemental data but no + additional data provider is configured, the supplemental data will not be + validated. + + + + + Provides additional data to be stored for the anti-forgery tokens generated + during this request. + + Information about the current request. + Supplemental data to embed within the anti-forgery token. + + + + Validates additional data that was embedded inside an incoming anti-forgery + token. + + Information about the current request. + Supplemental data that was embedded within the token. + True if the data is valid; false if the data is invalid. + + + + Initializes a new instance of the class. + + The base scope. + + The dictionary to use as a storage. Since the dictionary would be used as-is, we expect the implementer to + use the same key-value comparison logic as we do here. + + + + + Custom comparer for the context dictionaries + The comparer treats strings as a special case, performing case insesitive comparison. + This guaratees that we remain consistent throughout the chain of contexts since PageData dictionary + behaves in this manner. + + + + + End a ServiceStack Request + + + + + End a ServiceStack Request + + + + + End a HttpHandler Request + + + + + End a HttpHandler Request + + + + + End a ServiceStack Request with no content + + + + + Main container class for components, supporting container hierarchies and + lifetime management of instances. + + + + + Initializes a new empty container. + + + + + Creates a child container of the current one, which exposes its + current service registration to the new child container. + + + + + Disposes the container and all instances owned by it (see + ), as well as all child containers + created through . + + + + + Registers a service instance with the container. This instance + will have and + behavior. + Service instance to use. + + + + Registers a named service instance with the container. This instance + will have and + behavior. + Name of the service to register.Service instance to use. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service when needed. + Type of the service to retrieve.The function that can resolve to the service instance when invoked.The requested service has not been registered previously. + + + + + + + + + + + + + + + + + + + + + + Retrieves a function that can be used to lazily resolve an instance + of the service with the given name when needed. + Type of the service to retrieve.Name of the service to retrieve.The function that can resolve to the service instance with the given name when invoked.The requested service with the given name has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Registers the given service by providing a factory delegate to + instantiate it. + The service type to register.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.Sixth argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate to + instantiate it. + The service type to register.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.Sixth argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Resolves the given service by type, without passing any arguments for + its construction. + Type of the service to retrieve.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, without passing arguments for its initialization. + Type of the service to retrieve.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Attempts to resolve the given service by type, without passing arguments for its initialization. + Type of the service to retrieve. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, without passing + arguments arguments for its initialization. + Type of the service to retrieve. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Register an autowired dependency + + + + + + Register an autowired dependency as a separate type + + + + + + Alias for RegisterAutoWiredAs + + + + + + Auto-wires an existing instance, + ie all public properties are tried to be resolved. + + + + + + Generates a function which creates and auto-wires . + + + + + + + + Auto-wires an existing instance of a specific type. + The auto-wiring progress is also cached to be faster + when calling next time with the same type. + + + + + + Default owner for new registrations. by default. + + + + + Default reuse scope for new registrations. by default. + + + + + Enable the Registration feature and configure the RegistrationService. + + + + + Registers the type in the IoC container and + adds auto-wiring to the specified type. + + + + + + + Registers the type in the IoC container and + adds auto-wiring to the specified type. + The reuse scope is set to none (transient). + + + + + + Registers the types in the IoC container and + adds auto-wiring to the specified types. + The reuse scope is set to none (transient). + + + + + + Register a singleton instance as a runtime type + + + + + Encapsulates a method that has five parameters and returns a value of the + type specified by the parameter. + + + + + Encapsulates a method that has six parameters and returns a value of the + type specified by the parameter. + + + + + Encapsulates a method that has seven parameters and returns a value of the + type specified by the parameter. + + + + + Helper interface used to hide the base + members from the fluent API to make for much cleaner + Visual Studio intellisense experience. + + + + + + + + + + + + + + + + + Interface used by plugins to contribute registrations + to an existing container. + + + + + Determines who is responsible for disposing instances + registered with a container. + + + + + Container should dispose provided instances when it is disposed. This is the + default. + + + + + Container does not dispose provided instances. + + + + + Default owner, which equals . + + + + + Exception thrown by the container when a service cannot be resolved. + + + + + Initializes the exception with the service that could not be resolved. + + + + + Initializes the exception with the service (and its name) that could not be resolved. + + + + + Initializes the exception with an arbitrary message. + + + + + Determines visibility and reuse of instances provided by the container. + + + + + Instances are reused within a container hierarchy. Instances + are created (if necessary) in the container where the registration + was performed, and are reused by all descendent containers. + + + + + Instances are reused only at the given container. Descendent + containers do not reuse parent container instances and get + a new instance at their level. + + + + + Each request to resolve the dependency will result in a new + instance being returned. + + + + + Instaces are reused within the given request + + + + + Default scope, which equals . + + + + + Fluent API for customizing the registration of a service. + + + + + Fluent API that exposes both + and owner (). + + + + + Fluent API that allows specifying the reuse instances. + + + + + Specifies how instances are reused within a container or hierarchy. Default + scope is . + + + + + Fluent API that allows specifying the owner of instances + created from a registration. + + + + + Specifies the owner of instances created from this registration. Default + owner is . + + + + + Ownership setting for the service. + + + + + Reuse scope setting for the service. + + + + + The container where the entry was registered. + + + + + Specifies the owner for instances, which determines how + they will be disposed. + + + + + Specifies the scope for instances, which determines + visibility of instances across containers and hierarchies. + + + + + Fluent API for customizing the registration of a service. + + + + + Fluent API that allows registering an initializer for the + service. + + + + + Specifies an initializer that should be invoked after + the service instance has been created by the factory. + + + + + The Func delegate that creates instances of the service. + + + + + The cached service instance if the scope is or + . + + + + + The Func delegate that initializes the object after creation. + + + + + Clones the service entry assigning the to the + . Does not copy the . + + + + + BaseProfilerProvider. This providers some helper methods which provide access to + internals not otherwise available. + To use, override the , and + methods. + + + + + A provider used to create instances and maintain the current instance. + + + + + Starts a new MiniProfiler and sets it to be current. By the end of this method + should return the new MiniProfiler. + + + + + Ends the current profiling session, if one exists. + + + When true, clears the for this HttpContext, allowing profiling to + be prematurely stopped and discarded. Useful for when a specific route does not need to be profiled. + + + + + Returns the current MiniProfiler. This is used by . + + + + + + Starts a new MiniProfiler and sets it to be current. By the end of this method + should return the new MiniProfiler. + + + + + Stops the current MiniProfiler (if any is currently running). + should be called if is false + + If true, any current results will be thrown away and nothing saved + + + + Returns the current MiniProfiler. This is used by . + + + + + + Sets to be active (read to start profiling) + This should be called once a new MiniProfiler has been created. + + The profiler to set to active + If is null + + + + Stops the profiler and marks it as inactive. + + The profiler to stop + True if successful, false if Stop had previously been called on this profiler + If is null + + + + Calls to save the current + profiler using the current storage settings + + + + + + Categories of sql statements. + + + + + Unknown + + + + + DML statements that alter database state, e.g. INSERT, UPDATE + + + + + Statements that return a single record + + + + + Statements that iterate over a result set + + + + + A callback for ProfiledDbConnection and family + + + + + Called when a command starts executing + + + + + + + Called when a reader finishes executing + + + + + + + + Called when a reader is done iterating through the data + + + + + + Called when an error happens during execution of a command + + + + + + + + True if the profiler instance is active + + + + + This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), + and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE** + equality. The type is fully thread-safe. + + + + + If the underlying command supports BindByName, this sets/clears the underlying + implementation accordingly. This is required to support OracleCommand from dapper-dot-net + + + + + Wraps a database connection, allowing sql execution timings to be collected when a session is started. + + + + + This will be made private; use + + + + + This will be made private; use + + + + + Returns a new that wraps , + providing query execution profiling. If profiler is null, no profiling will occur. + + Your provider-specific flavor of connection, e.g. SqlConnection, OracleConnection + The currently started or null. + Determines whether the ProfiledDbConnection will dispose the underlying connection. + + + + The underlying, real database connection to your db provider. + + + + + The current profiler instance; could be null. + + + + + The raw connection this is wrapping + + + + + Wrapper for a db provider factory to enable profiling + + + + + Every provider factory must have an Instance public field + + + + + Used for db provider apis internally + + + + + Allow to re-init the provider factory. + + + + + + + proxy + + + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + Common extension methods to use only in this project + + + + + Answers true if this String is either null or empty. + + + + + Answers true if this String is neither null or empty. + + + + + Removes trailing / characters from a path and leaves just one + + + + + Removes any leading / characters from a path + + + + + Removes any leading / characters from a path + + + + + Serializes to a json string. + + + + + Gets part of a stack trace containing only methods we care about. + + + + + Gets the current formatted and filted stack trace. + + Space separated list of methods + + + + Identifies users based on ip address. + + + + + Provides functionality to identify which user is profiling a request. + + + + + Returns a string to identify the user profiling the current 'request'. + + The current HttpRequest being profiled. + + + + Returns the paramter HttpRequest's client ip address. + + + + + A single MiniProfiler can be used to represent any number of steps/levels in a call-graph, via Step() + + Totally baller. + + + + Starts when this profiler is instantiated. Each step will use this Stopwatch's current ticks as + their starting time. + + + + + Creates and starts a new MiniProfiler for the root , filtering steps to . + + + + + Returns the 's and this profiler recorded. + + + + + Returns true if Ids match. + + + + + Returns hashcode of Id. + + + + + Obsolete - used for serialization. + + + + + Walks the hierarchy contained in this profiler, starting with , and returns each Timing found. + + + + + Returns milliseconds based on Stopwatch's Frequency. + + + + + Starts a new MiniProfiler based on the current . This new profiler can be accessed by + + + + + + Ends the current profiling session, if one exists. + + + When true, clears the for this HttpContext, allowing profiling to + be prematurely stopped and discarded. Useful for when a specific route does not need to be profiled. + + + + + Returns an that will time the code between its creation and disposal. Use this method when you + do not wish to include the MvcMiniProfiler namespace for the extension method. + + A descriptive name for the code that is encapsulated by the resulting IDisposable's lifetime. + This step's visibility level; allows filtering when is called. + + + + Returns the css and javascript includes needed to display the MiniProfiler results UI. + + Which side of the page the profiler popup button should be displayed on (defaults to left) + Whether to show trivial timings by default (defaults to false) + Whether to show time the time with children column by default (defaults to false) + The maximum number of trace popups to show before removing the oldest (defaults to 15) + xhtml rendering mode, ensure script tag is closed ... etc + when true, shows buttons to minimize and clear MiniProfiler results + Script and link elements normally; an empty string when there is no active profiling session. + + + + Renders the current to json. + + + + + Renders the parameter to json. + + + + + Deserializes the json string parameter to a . + + + + + Create a DEEP clone of this object + + + + + + Returns all currently open commands on this connection + + + + + Returns all results contained in all child steps. + + + + + Contains any sql statements that are executed, along with how many times those statements are executed. + + + + + Adds to the current . + + + + + Returns the number of sql statements of that were executed in all s. + + + + + Identifies this Profiler so it may be stored/cached. + + + + + A display name for this profiling session. + + + + + When this profiler was instantiated. + + + + + Where this profiler was run. + + + + + Allows filtering of steps based on what + the steps are created with. + + + + + The first that is created and started when this profiler is instantiated. + All other s will be children of this one. + + + + + A string identifying the user/client that is profiling this request. Set + with an -implementing class to provide a custom value. + + + If this is not set manually at some point, the implementation will be used; + by default, this will be the current request's ip address. + + + + + Returns true when this MiniProfiler has been viewed by the that recorded it. + + + Allows POSTs that result in a redirect to be profiled. implementation + will keep a list of all profilers that haven't been fetched down. + + + + + For unit testing, returns the timer. + + + + + Milliseconds, to one decimal place, that this MiniProfiler ran. + + + + + Returns true when or any of its are . + + + + + Returns true when all child s are . + + + + + Any Timing step with a duration less than or equal to this will be hidden by default in the UI; defaults to 2.0 ms. + + + + + Ticks since this MiniProfiler was started. + + + + + Json representing the collection of CustomTimings relating to this Profiler + + + Is used when storing the Profiler in SqlStorage + + + + + Points to the currently executing Timing. + + + + + Gets the currently running MiniProfiler for the current HttpContext; null if no MiniProfiler was ed. + + + + + Contains information about queries executed during this profiling session. + + + + + Milliseconds, to one decimal place, that this MiniProfiler was executing sql. + + + + + Returns true when we have profiled queries. + + + + + Returns true when any child Timings have duplicate queries. + + + + + How many sql data readers were executed in all steps. + + + + + How many sql scalar queries were executed in all steps. + + + + + How many sql non-query statements were executed in all steps. + + + + + Various configuration properties. + + + + + Excludes the specified assembly from the stack trace output. + + The short name of the assembly. AssemblyName.Name + + + + Excludes the specified type from the stack trace output. + + The System.Type name to exclude + + + + Excludes the specified method name from the stack trace output. + + The name of the method + + + + Make sure we can at least store profiler results to the http runtime cache. + + + + + Assemblies to exclude from the stack trace report. + + + + + Types to exclude from the stack trace report. + + + + + Methods to exclude from the stack trace report. + + + + + The max length of the stack string to report back; defaults to 120 chars. + + + + + Any Timing step with a duration less than or equal to this will be hidden by default in the UI; defaults to 2.0 ms. + + + + + Dictates if the "time with children" column is displayed by default, defaults to false. + For a per-page override you can use .RenderIncludes(showTimeWithChildren: true/false) + + + + + Dictates if trivial timings are displayed by default, defaults to false. + For a per-page override you can use .RenderIncludes(showTrivial: true/false) + + + + + Determines how many traces to show before removing the oldest; defaults to 15. + For a per-page override you can use .RenderIncludes(maxTracesToShow: 10) + + + + + Dictates on which side of the page the profiler popup button is displayed; defaults to left. + For a per-page override you can use .RenderIncludes(position: RenderPosition.Left/Right) + + + + + Determines if min-max, clear, etc are rendered; defaults to false. + For a per-page override you can use .RenderIncludes(showControls: true/false) + + + + + By default, SqlTimings will grab a stack trace to help locate where queries are being executed. + When this setting is true, no stack trace will be collected, possibly improving profiler performance. + + + + + When is called, if the current request url contains any items in this property, + no profiler will be instantiated and no results will be displayed. + Default value is { "/ssr-", "/content/", "/scripts/", "/favicon.ico" }. + + + + + The path under which ALL routes are registered in, defaults to the application root. For example, "~/myDirectory/" would yield + "/myDirectory/ssr-includes.js" rather than just "/mini-profiler-includes.js" + Any setting here should be in APP RELATIVE FORM, e.g. "~/myDirectory/" + + + + + Understands how to save and load MiniProfilers. Used for caching between when + a profiling session ends and results can be fetched to the client, and for showing shared, full-page results. + + + The normal profiling session life-cycle is as follows: + 1) request begins + 2) profiler is started + 3) normal page/controller/request execution + 4) profiler is stopped + 5) profiler is cached with 's implementation of + 6) request ends + 7) page is displayed and profiling results are ajax-fetched down, pulling cached results from + 's implementation of + + + + + The formatter applied to the SQL being rendered (used only for UI) + + + + + Assembly version of this dank MiniProfiler. + + + + + The provider used to provider the current instance of a provider + This is also + + + + + A function that determines who can access the MiniProfiler results url. It should return true when + the request client has access, false for a 401 to be returned. HttpRequest parameter is the current request and + MiniProfiler parameter is the results that were profiled. + + + Both the HttpRequest and MiniProfiler parameters that will be passed into this function should never be null. + + + + + Allows switching out stopwatches for unit testing. + + + + + Categorizes individual steps to allow filtering. + + + + + Default level given to Timings. + + + + + Useful when profiling many items in a loop, but you don't wish to always see this detail. + + + + + Dictates on which side of the page the profiler popup button is displayed; defaults to left. + + + + + Profiler popup button is displayed on the left. + + + + + Profiler popup button is displayed on the right. + + + + + Contains helper methods that ease working with null s. + + + + + Wraps in a call and executes it, returning its result. + + The current profiling session or null. + Method to execute and profile. + The step name used to label the profiler results. + + + + + Returns an that will time the code between its creation and disposal. + + The current profiling session or null. + A descriptive name for the code that is encapsulated by the resulting IDisposable's lifetime. + This step's visibility level; allows filtering when is called. + + + + Adds 's hierarchy to this profiler's current Timing step, + allowing other threads, remote calls, etc. to be profiled and joined into this profiling session. + + + + + Returns an html-encoded string with a text-representation of ; returns "" when profiler is null. + + The current profiling session or null. + + + + Formats any SQL query with inline parameters, optionally including the value type + + + + + Takes a SqlTiming and returns a formatted SQL string, for parameter replacement, etc. + + + + + Return SQL the way you want it to look on the in the trace. Usually used to format parameters + + + Formatted SQL + + + + Creates a new Inline SQL Formatter, optionally including the parameter type info in comments beside the replaced value + + whether to include a comment after the value, indicating the type, e.g. /* @myParam DbType.Int32 */ + + + + Formats the SQL in a generic frieldly format, including the parameter type information in a comment if it was specified in the InlineFormatter constructor + + The SqlTiming to format + A formatted SQL string + + + + Returns a string representation of the parameter's value, including the type + + The parameter to get a value for + + + + + NOT IMPLEMENTED - will format statements with paramters in an Oracle friendly way + + + + + Does NOTHING, implement me! + + + + + Formats SQL server queries with a DECLARE up top for parameter values + + + + + Formats the SQL in a SQL-Server friendly way, with DECLARE statements for the parameters up top. + + The SqlTiming to format + A formatted SQL string + + + + Contains helper code to time sql statements. + + + + + Returns a new SqlProfiler to be used in the 'profiler' session. + + + + + Tracks when 'command' is started. + + + + + Returns all currently open commands on this connection + + + + + Finishes profiling for 'command', recording durations. + + + + + Called when 'reader' finishes its iterations and is closed. + + + + + The profiling session this SqlProfiler is part of. + + + + + Helper methods that allow operation on SqlProfilers, regardless of their instantiation. + + + + + Tracks when 'command' is started. + + + + + Finishes profiling for 'command', recording durations. + + + + + Called when 'reader' finishes its iterations and is closed. + + + + + Profiles a single sql execution. + + + + + Creates a new SqlTiming to profile 'command'. + + + + + Obsolete - used for serialization. + + + + + Returns a snippet of the sql command and the duration. + + + + + Returns true if Ids match. + + + + + Returns hashcode of Id. + + + + + Called when command execution is finished to determine this SqlTiming's duration. + + + + + Called when database reader is closed, ending profiling for SqlTimings. + + + + + To help with display, put some space around sammiched commas + + + + + Unique identifier for this SqlTiming. + + + + + Category of sql statement executed. + + + + + The sql that was executed. + + + + + The command string with special formatting applied based on MiniProfiler.Settings.SqlFormatter + + + + + Roughly where in the calling code that this sql was executed. + + + + + Offset from main MiniProfiler start that this sql began. + + + + + How long this sql statement took to execute. + + + + + When executing readers, how long it took to come back initially from the database, + before all records are fetched and reader is closed. + + + + + Stores any parameter names and values used by the profiled DbCommand. + + + + + Id of the Timing this statement was executed in. + + + Needed for database deserialization. + + + + + The Timing step that this sql execution occurred in. + + + + + True when other identical sql statements have been executed during this MiniProfiler session. + + + + + Information about a DbParameter used in the sql statement profiled by SqlTiming. + + + + + Returns true if this has the same parent , and as . + + + + + Returns the XOR of certain properties. + + + + + Which SqlTiming this Parameter was executed with. + + + + + Parameter name, e.g. "@routeName" + + + + + The value submitted to the database. + + + + + System.Data.DbType, e.g. "String", "Bit" + + + + + How large the type is, e.g. for string, size could be 4000 + + + + + Understands how to save MiniProfiler results to a MSSQL database, allowing more permanent storage and + querying of slow results. + + + + + Provides saving and loading s to a storage medium. + + + + + Stores under its . + + The results of a profiling session. + + Should also ensure the profiler is stored as being unviewed by its profiling . + + + + + Returns a from storage based on , which should map to . + + + Should also update that the resulting profiler has been marked as viewed by its profiling . + + + + + Returns a list of s that haven't been seen by . + + User identified by the current . + + + + Returns a new SqlServerDatabaseStorage object that will insert into the database identified by connectionString. + + + + + Saves 'profiler' to a database under its . + + + + + Returns the MiniProfiler identified by 'id' from the database or null when no MiniProfiler exists under that 'id'. + + + + + Returns a list of s that haven't been seen by . + + User identified by the current . + + + + Returns a DbConnection for your specific provider. + + + + + Returns a DbConnection already opened for execution. + + + + + How we connect to the database used to save/load MiniProfiler results. + + + + + Understands how to store a to the with absolute expiration. + + + + + The string that prefixes all keys that MiniProfilers are saved under, e.g. + "mini-profiler-ecfb0050-7ce8-4bf1-bf82-2cb38e90e31e". + + + + + Returns a new HttpRuntimeCacheStorage class that will cache MiniProfilers for the specified duration. + + + + + Saves to the HttpRuntime.Cache under a key concated with + and the parameter's . + + + + + Returns the saved identified by . Also marks the resulting + profiler to true. + + + + + Returns a list of s that haven't been seen by . + + User identified by the current . + + + + Syncs access to runtime cache when adding a new list of ids for a user. + + + + + How long to cache each for (i.e. the absolute expiration parameter of + ) + + + + + An individual profiling step that can contain child steps. + + + + + Rebuilds all the parent timings on deserialization calls + + + + + Offset from parent MiniProfiler's creation that this Timing was created. + + + + + Creates a new Timing named 'name' in the 'profiler's session, with 'parent' as this Timing's immediate ancestor. + + + + + Obsolete - used for serialization. + + + + + Returns this Timing's Name. + + + + + Returns true if Ids match. + + + + + Returns hashcode of Id. + + + + + Adds arbitrary string 'value' under 'key', allowing custom properties to be stored in this Timing step. + + + + + Completes this Timing's duration and sets the MiniProfiler's Head up one level. + + + + + Add the parameter 'timing' to this Timing's Children collection. + + + Used outside this assembly for custom deserialization when creating an implementation. + + + + + Adds the parameter 'sqlTiming' to this Timing's SqlTimings collection. + + A sql statement profiling that was executed in this Timing step. + + Used outside this assembly for custom deserialization when creating an implementation. + + + + + Returns the number of sql statements of that were executed in this . + + + + + Unique identifer for this timing; set during construction. + + + + + Text displayed when this Timing is rendered. + + + + + How long this Timing step took in ms; includes any Timings' durations. + + + + + The offset from the start of profiling. + + + + + All sub-steps that occur within this Timing step. Add new children through + + + + + Stores arbitrary key/value strings on this Timing step. Add new tuples through . + + + + + Any queries that occurred during this Timing step. + + + + + Needed for database deserialization and JSON serialization. + + + + + Which Timing this Timing is under - the duration that this step takes will be added to its parent's duration. + + This will be null for the root (initial) Timing. + + + + Gets the elapsed milliseconds in this step without any children's durations. + + + + + Gets the aggregate elapsed milliseconds of all SqlTimings executed in this Timing, excluding Children Timings. + + + + + Returns true when this is less than the configured + , by default 2.0 ms. + + + + + Reference to the containing profiler, allowing this Timing to affect the Head and get Stopwatch readings. + + + + + Returns true when this Timing has inner Timing steps. + + + + + Returns true if this Timing step collected sql execution timings. + + + + + Returns true if any s executed in this step are detected as duplicate statements. + + + + + Returns true when this Timing is the first one created in a MiniProfiler session. + + + + + How far away this Timing is from the Profiler's Root. + + + + + How many sql data readers were executed in this Timing step. Does not include queries in any child Timings. + + + + + How many sql scalar queries were executed in this Timing step. Does not include queries in any child Timings. + + + + + How many sql non-query statements were executed in this Timing step. Does not include queries in any child Timings. + + + + + Understands how to route and respond to MiniProfiler UI urls. + + + + + Returns either includes' css/javascript or results' html. + + + + + Handles rendering static content files. + + + + + Handles rendering a previous MiniProfiler session, identified by its "?id=GUID" on the query. + + + + + Embedded resource contents keyed by filename. + + + + + Helper method that sets a proper 404 response code. + + + + + Try to keep everything static so we can easily be reused. + + + + + HttpContext based profiler provider. This is the default provider to use in a web context. + The current profiler is associated with a HttpContext.Current ensuring that profilers are + specific to a individual HttpRequest. + + + + + Public constructor. This also registers any UI routes needed to display results + + + + + Starts a new MiniProfiler and associates it with the current . + + + + + Ends the current profiling session, if one exists. + + + When true, clears the for this HttpContext, allowing profiling to + be prematurely stopped and discarded. Useful for when a specific route does not need to be profiled. + + + + + Makes sure 'profiler' has a Name, pulling it from route data or url. + + + + + Returns the current profiler + + + + + + Gets the currently running MiniProfiler for the current HttpContext; null if no MiniProfiler was ed. + + + + + WebRequestProfilerProvider specific configurations + + + + + Provides user identification for a given profiling request. + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has specific permissions. + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has specific roles. + + + + + Check all session is in all supplied roles otherwise a 401 HttpError is thrown + + + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has specific permissions. + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has any of the specified roles. + + + + + Check all session is in any supplied roles otherwise a 401 HttpError is thrown + + + + + + + Base class to create response filter attributes only for specific HTTP methods (GET, POST...) + + + + + Creates a new + + Defines when the filter should be executed + + + + This method is only executed if the HTTP method matches the property. + + The http request wrapper + The http response wrapper + The response DTO + + + + Create a ShallowCopy of this instance. + + + + + + If they don't have an ICacheClient configured use an In Memory one. + + + + + Creates instance using straight Resolve approach. + This will throw an exception if resolution fails + + + + + Creates instance using the TryResolve approach if tryResolve = true. + Otherwise uses Resolve approach, which will throw an exception if resolution fails + + + + + Sets a persistent cookie which never expires + + + + + Sets a session cookie which expires after the browser session closes + + + + + Deletes a specified cookie by setting its value to empty and expiration to -1 days + + + + + Lets you Register new Services and the optional restPaths will be registered against + this default Request Type + + + + + Naming convention for the ResponseStatus property name on the response DTO + + + + + Create an instance of the service response dto type and inject it with the supplied responseStatus + + + + + + + + + + + + + + + + + Override to provide additional/less context about the Service Exception. + By default the request is serialized and appended to the ResponseStatus StackTrace. + + + + + Scans the supplied Assemblies to infer REST paths and HTTP verbs. + + The instance. + + The assemblies with REST services. + + The same instance; + never . + + + + Configure ServiceStack to have ISession support + + + + + Create the active Session or Permanent Session Id cookie. + + + + + + Create both Permanent and Session Id cookies and return the active sessionId + + + + + + This class interecepts 401 requests and changes them to 402 errors. When this happens the FormAuthentication module + will no longer hijack it and redirect back to login because it is a 402 error, not a 401. + When the request ends, this class sets the status code back to 401 and everything works as it should. + + PathToSupress is the path inside your website where the above swap should happen. + + If you can build for .net 4.5, you do not have to do this swap. You can take advantage of a new flag (SuppressFormsAuthenticationRedirect) + that tells the FormAuthenticationModule to not redirect, which also means you will not need the EndRequest code. + + + + + Converts the validation result to an error result which will be serialized by ServiceStack in a clean and human-readable way. + + The validation result + + + + + Converts the validation result to an error exception which will be serialized by ServiceStack in a clean and human-readable way + if the returned exception is thrown. + + The validation result + + + + + Creates a new instance of the RulesetValidatorSelector. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Activate the validation mechanism, so every request DTO with an existing validator + will be validated. + + The app host + + + + Override to provide additional/less context about the Service Exception. + By default the request is serialized and appended to the ResponseStatus StackTrace. + + + + + Auto-scans the provided assemblies for a + and registers it in the provided IoC container. + + The IoC container + The assemblies to scan for a validator + + + + In Memory repository for files. Useful for testing. + + + + + Context to capture IService action + + + + + Get an IAppHost container. + Note: Registering dependencies should only be done during setup/configuration + stage and remain immutable there after for thread-safety. + + + + + + + Ensure the same instance is used for subclasses + + + + + Called before page is executed + + + + + Called after page is executed but before it's merged with the + website template if any. + + + + + Don't HTML encode safe output + + + + + + + Return the output of a different view with the specified name + using the supplied model + + + + + + + + Resolve registered Assemblies + + + + + + Reference to MarkdownViewEngine + + + + + The AppHost so you can access configuration and resolve dependencies, etc. + + + + + This precompiled Markdown page with Metadata + + + + + ASP.NET MVC's HtmlHelper + + + + + All variables passed to and created by your page. + The Response DTO is stored and accessible via the 'Model' variable. + + All variables and outputs created are stored in ScopeArgs which is what's available + to your website template. The Generated page is stored in the 'Body' variable. + + + + + Whether HTML or Markdown output is requested + + + + + The Response DTO + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to Container service is built-in and read-only.. + + + + + Looks up a localized string similar to Service type {0} does not inherit or implement {1}.. + + + + + Looks up a localized string similar to Required dependency of type {0} named '{1}' could not be resolved.. + + + + + Looks up a localized string similar to Required dependency of type {0} could not be resolved.. + + + + + Looks up a localized string similar to Unknown scope.. + + + + + Gets string value from Items[name] then Cookies[name] if exists. + Useful when *first* setting the users response cookie in the request filter. + To access the value for this initial request you need to set it in Items[]. + + string value or null if it doesn't exist + + + + Gets request paramater string value by looking in the following order: + - QueryString[name] + - FormData[name] + - Cookies[name] + - Items[name] + + string value or null if it doesn't exist + + + * + Input: http://localhost:96/Cambia3/Temp/Test.aspx/path/info?q=item#fragment + + Some HttpRequest path and URL properties: + Request.ApplicationPath: /Cambia3 + Request.CurrentExecutionFilePath: /Cambia3/Temp/Test.aspx + Request.FilePath: /Cambia3/Temp/Test.aspx + Request.Path: /Cambia3/Temp/Test.aspx/path/info + Request.PathInfo: /path/info + Request.PhysicalApplicationPath: D:\Inetpub\wwwroot\CambiaWeb\Cambia3\ + Request.QueryString: /Cambia3/Temp/Test.aspx/path/info?query=arg + Request.Url.AbsolutePath: /Cambia3/Temp/Test.aspx/path/info + Request.Url.AbsoluteUri: http://localhost:96/Cambia3/Temp/Test.aspx/path/info?query=arg + Request.Url.Fragment: + Request.Url.Host: localhost + Request.Url.LocalPath: /Cambia3/Temp/Test.aspx/path/info + Request.Url.PathAndQuery: /Cambia3/Temp/Test.aspx/path/info?query=arg + Request.Url.Port: 96 + Request.Url.Query: ?query=arg + Request.Url.Scheme: http + Request.Url.Segments: / + Cambia3/ + Temp/ + Test.aspx/ + path/ + info + * + + + + Use this to treat Request.Items[] as a cache by returning pre-computed items to save + calculating them multiple times. + + + + + Sets a persistent cookie which never expires + + + + + Sets a session cookie which expires after the browser session closes + + + + + Sets a persistent cookie which expires after the given time + + + + + Sets a persistent cookie with an expiresAt date + + + + + Deletes a specified cookie by setting its value to empty and expiration to -1 days + + + + + Returns the optimized result for the IRequestContext. + Does not use or store results in any cache. + + + + + + + + Overload for the method returning the most + optimized result based on the MimeType and CompressionType from the IRequestContext. + + + + + Overload for the method returning the most + optimized result based on the MimeType and CompressionType from the IRequestContext. + How long to cache for, null is no expiration + + + + + Clears all the serialized and compressed caches set + by the 'Resolve' method for the cacheKey provided + + + + + + + + Store an entry in the IHttpRequest.Items Dictionary + + + + + Get an entry from the IHttpRequest.Items Dictionary + + + + + For performance withPathInfoParts should already be a lower case string + to minimize redundant matching operations. + + + + + + + + For performance withPathInfoParts should already be a lower case string + to minimize redundant matching operations. + + + + + + + + + The number of segments separated by '/' determinable by path.Split('/').Length + e.g. /path/to/here.ext == 3 + + + + + The total number of segments after subparts have been exploded ('.') + e.g. /path/to/here.ext == 4 + + + + + Provide for quick lookups based on hashes that can be determined from a request url + + + + + Execute MQ + + + + + Execute MQ with requestContext + + + + + Execute using empty RequestContext + + + + + Execute HTTP + + + + + Gets the name of the base most type in the heirachy tree with the same. + + We get an exception when trying to create a schema with multiple types of the same name + like when inheriting from a DataContract with the same name. + + The type. + + + + + Inherit from this class if you want to host your web services inside an + ASP.NET application. + + + + + Exécute les tâches définies par l'application associées à la libération ou à la redéfinition des ressources non managées. + + 2 + + + + Load Embedded Resource Templates in ServiceStack. + To get ServiceStack to use your own instead just add a copy of one or more of the following to your Web Root: + ~/Templates/IndexOperations.html + ~/Templates/OperationControl.html + ~/Templates/HtmlFormat.html + + + + + when true, (most) bare plain URLs are auto-hyperlinked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, RETURN becomes a literal newline + WARNING: this is a significant deviation from the markdown spec + + + + + use ">" for HTML output, or " />" for XHTML output + + + + + when true, problematic URL characters like [, ], (, and so forth will be encoded + WARNING: this is a significant deviation from the markdown spec + + + + + when false, email addresses will never be auto-linked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, bold and italic require non-word characters on either side + WARNING: this is a significant deviation from the markdown spec + + + + + Markdown is a text-to-HTML conversion tool for web writers. + Markdown allows you to write using an easy-to-read, easy-to-write plain text format, + then convert it to structurally valid XHTML (or HTML). + + + + + Tabs are automatically converted to spaces as part of the transform + this constant determines how "wide" those tabs become in spaces + + + + + Create a new Markdown instance using default options + + + + + Create a new Markdown instance and optionally load options from a configuration + file. There they should be stored in the appSettings section, available options are: + + Markdown.StrictBoldItalic (true/false) + Markdown.EmptyElementSuffix (">" or " />" without the quotes) + Markdown.LinkEmails (true/false) + Markdown.AutoNewLines (true/false) + Markdown.AutoHyperlink (true/false) + Markdown.EncodeProblemUrlCharacters (true/false) + + + + + + Create a new Markdown instance and set the options from the MarkdownOptions object. + + + + + maximum nested depth of [] and () supported by the transform; implementation detail + + + + + In the static constuctor we'll initialize what stays the same across all transforms. + + + + + Transforms the provided Markdown-formatted text to HTML; + see http://en.wikipedia.org/wiki/Markdown + + + The order in which other subs are called here is + essential. Link and image substitutions need to happen before + EscapeSpecialChars(), so that any *'s or _'s in the a + and img tags get encoded. + + + + + Perform transformations that form block-level tags like paragraphs, headers, and list items. + + + + + Perform transformations that occur *within* block-level tags like paragraphs, headers, and list items. + + + + + splits on two or more newlines, to form "paragraphs"; + each paragraph is then unhashed (if it is a hash and unhashing isn't turned off) or wrapped in HTML p tag + + + + + Reusable pattern to match balanced [brackets]. See Friedl's + "Mastering Regular Expressions", 2nd Ed., pp. 328-331. + + + + + Reusable pattern to match balanced (parens). See Friedl's + "Mastering Regular Expressions", 2nd Ed., pp. 328-331. + + + + + Strips link definitions from text, stores the URLs and titles in hash references. + + + ^[id]: url "optional title" + + + + + derived pretty much verbatim from PHP Markdown + + + + + replaces any block-level HTML blocks with hash entries + + + + + returns an array of HTML tokens comprising the input string. Each token is + either a tag (possibly with nested, tags contained therein, such + as <a href="<MTFoo>">, or a run of text between tags. Each element of the + array is a two-element array; the first is either 'tag' or 'text'; the second is + the actual value. + + + + + Turn Markdown link shortcuts into HTML anchor tags + + + [link text](url "title") + [link text][id] + [id] + + + + + Turn Markdown image shortcuts into HTML img tags. + + + ![alt text][id] + ![alt text](url "optional title") + + + + + Turn Markdown headers into HTML header tags + + + Header 1 + ======== + + Header 2 + -------- + + # Header 1 + ## Header 2 + ## Header 2 with closing hashes ## + ... + ###### Header 6 + + + + + Turn Markdown horizontal rules into HTML hr tags + + + *** + * * * + --- + - - - + + + + + Turn Markdown lists into HTML ul and ol and li tags + + + + + Process the contents of a single ordered or unordered list, splitting it + into individual list items. + + + + + /// Turn Markdown 4-space indented code into HTML pre code blocks + + + + + Turn Markdown `code spans` into HTML code tags + + + + + Turn Markdown *italics* and **bold** into HTML strong and em tags + + + + + Turn markdown line breaks (two space at end of line) into HTML break tags + + + + + Turn Markdown > quoted blocks into HTML blockquote blocks + + + + + Turn angle-delimited URLs into HTML anchor tags + + + <http://www.example.com> + + + + + Remove one level of line-leading spaces + + + + + encodes email address randomly + roughly 10% raw, 45% hex, 45% dec + note that @ is always encoded and : never is + + + + + Encode/escape certain Markdown characters inside code blocks and spans where they are literals + + + + + Encode any ampersands (that aren't part of an HTML entity) and left or right angle brackets + + + + + Encodes any escaped characters such as \`, \*, \[ etc + + + + + swap back in all the special characters we've hidden + + + + + escapes Bold [ * ] and Italic [ _ ] characters + + + + + hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems + + + + + Within tags -- meaning between < and > -- encode [\ ` * _] so they + don't conflict with their use in Markdown for code, italics and strong. + We're replacing each such character with its corresponding hash + value; this is likely overkill, but it should prevent us from colliding + with the escape values by accident. + + + + + convert all tabs to _tabWidth spaces; + standardizes line endings from DOS (CR LF) or Mac (CR) to UNIX (LF); + makes sure text ends with a couple of newlines; + removes any blank lines (only spaces) in the text + + + + + this is to emulate what's evailable in PHP + + + + + use ">" for HTML output, or " />" for XHTML output + + + + + when false, email addresses will never be auto-linked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, bold and italic require non-word characters on either side + WARNING: this is a significant deviation from the markdown spec + + + + + when true, RETURN becomes a literal newline + WARNING: this is a significant deviation from the markdown spec + + + + + when true, (most) bare plain URLs are auto-hyperlinked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, problematic URL characters like [, ], (, and so forth will be encoded + WARNING: this is a significant deviation from the markdown spec + + + + + current version of MarkdownSharp; + see http://code.google.com/p/markdownsharp/ for the latest code or to contribute + + + + + Render Markdown for text/markdown and text/plain ContentTypes + + + + + Used in Unit tests + + + + + + Non ASP.NET requests + + + + + + + + ASP.NET requests + + + + + + Writes to response. + Response headers are customizable by implementing IHasOptions an returning Dictionary of Http headers. + + The response. + Whether or not it was implicity handled by ServiceStack's built-in handlers. + The default action. + The serialization context. + Add prefix to response body if any + Add suffix to response body if any + + + + + Highly optimized code to find if GZIP is supported from: + - http://dotnetperls.com/gzip-request + + Other resources for GZip, deflate resources: + - http://www.west-wind.com/Weblog/posts/10564.aspx + - http://www.west-wind.com/WebLog/posts/102969.aspx + - ICSharpCode + + + + + Changes the links for the servicestack/metadata page + + + + + Non ASP.NET requests + + + + + ASP.NET requests + + + + + Keep default file contents in-memory + + + + + + Call to signal the completion of a ServiceStack-handled Request + + + + + Resolves and auto-wires a ServiceStack Service from a ASP.NET HttpContext. + + + + + Resolves and auto-wires a ServiceStack Service from a HttpListenerContext. + + + + + Resolves and auto-wires a ServiceStack Service. + + + + diff --git a/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/ServiceStack.Client.4.0.11.nupkg b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/ServiceStack.Client.4.0.11.nupkg new file mode 100644 index 00000000..729cf384 Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/ServiceStack.Client.4.0.11.nupkg differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.dll b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.dll new file mode 100644 index 00000000..661af9fb Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.xml b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.xml new file mode 100644 index 00000000..1811c5ff --- /dev/null +++ b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.xml @@ -0,0 +1,383 @@ + + + + ServiceStack.Client + + + + Need to provide async request options + http://msdn.microsoft.com/en-us/library/86wf6409(VS.71).aspx + + + + The request filter is called before any request. + This request filter is executed globally. + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + This response action is executed globally. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Called before request resend, when the initial request required authentication + + + + + The request filter is called before any request. + This request filter only works with the instance where it was set (not global). + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Returns the next message from queueName or null if no message + + + + + + + Generic Proxy for service calls. + + The service Contract + + + + Returns the transparent proxy for the service call + + + + Need to provide async request options + http://msdn.microsoft.com/en-us/library/86wf6409(VS.71).aspx + + + + The request filter is called before any request. + This request filter is executed globally. + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + This response action is executed globally. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Sets all baseUri properties, using the Format property for the SyncReplyBaseUri and AsyncOneWayBaseUri + + Base URI of the service + + + + Whether to Accept Gzip,Deflate Content-Encoding and to auto decompress responses + + + + + The user name for basic authentication + + + + + The password for basic authentication + + + + + Sets the username and the password for basic authentication. + + + + + Determines if the basic auth header should be sent with every request. + By default, the basic auth header is only sent when "401 Unauthorized" is returned. + + + + + Specifies if cookies should be stored + + + + + Called by Send method if an exception occurs, for instance a System.Net.WebException because the server + returned an HTTP error code. Override if you want to handle specific exceptions or always want to parse the + response to a custom ErrorResponse DTO type instead of ServiceStack's ErrorResponse class. In case ex is a + System.Net.WebException, do not use + createWebRequest/getResponse/HandleResponse<TResponse> to parse the response + because that will result in the same exception again. Use + ThrowWebServiceException<YourErrorResponseType> to parse the response and to throw a + WebServiceException containing the parsed DTO. Then override Send to handle that exception. + + + + + Gets the collection of headers to be added to outgoing requests. + + + + + Gets or sets authentication information for the request. + Warning: It's recommened to use and for basic auth. + This property is only used for IIS level authentication. + + + + + Called before request resend, when the initial request required authentication + + + + + The request filter is called before any request. + This request filter only works with the instance where it was set (not global). + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Track any IDisposable's to dispose of at the end of the request in IAppHost.OnEndRequest() + + + + + + Gets a list of items for this request. + + This list will be cleared on every request and is specific to the original thread that is handling the request. + If a handler uses additional threads, this data will not be available on those threads. + + + + + Creates the error response from the values provided. + + If the errorCode is empty it will use the first validation error code, + if there is none it will throw an error. + + The error code. + The error message. + The validation errors. + + + + + Default MaxStringContentLength is 8k, and throws an exception when reached + + + + + Serializer cache of delegates required to create a type from a string map (e.g. for REST urls) + + + + + Gets the namespace from an attribute marked on the type's definition + + + Namespace of type + + + + Specifies if cookies should be stored + + + + + Compresses the specified text using the default compression method: Deflate + + The text. + Type of the compression. + + + + + Decompresses the specified gz buffer using the default compression method: Inflate + + The gz buffer. + Type of the compression. + + + + + Donated by Ivan Korneliuk from his post: + http://korneliuk.blogspot.com/2012/08/servicestack-reusing-dtos.html + + Modified to only allow using routes matching the supplied HTTP Verb + + + + + Generate a url from a Request DTO. Pretty URL generation require Routes to be defined using `[Route]` on the Request DTO + + + + + The exception which is thrown when a validation error occurred. + This validation is serialized in a extra clean and human-readable way by ServiceStack. + + + + + Used if we need to serialize this exception to XML + + + + + + Returns the first error code + + The error code. + + + + Encapsulates a validation result. + + + + + Constructs a new ValidationResult + + + + + Constructs a new ValidationResult + + A list of validation results + + + + Initializes a new instance of the class. + + The errors. + The success code. + The error code. + + + + Merge errors from another + + + + + + Gets or sets the success code. + + The success code. + + + + Gets or sets the error code. + + The error code. + + + + Gets or sets the success message. + + The success message. + + + + Gets or sets the error message. + + The error message. + + + + The errors generated by the validation. + + + + + Returns True if the validation was successful (errors list is empty). + + + + + Adds the singleton instance of to an endpoint on the client. + + + Based on http://megakemp.wordpress.com/2009/02/06/managing-shared-cookies-in-wcf/ + + + + + Adds the singleton of the class to the client endpoint's message inspectors. + + The endpoint that is to be customized. + The client runtime to be customized. + + + + Maintains a copy of the cookies contained in the incoming HTTP response received from any service + and appends it to all outgoing HTTP requests. + + + This class effectively allows to send any received HTTP cookies to different services, + reproducing the same functionality available in ASMX Web Services proxies with the class. + Based on http://megakemp.wordpress.com/2009/02/06/managing-shared-cookies-in-wcf/ + + + + + Initializes a new instance of the class. + + + + + Inspects a message after a reply message is received but prior to passing it back to the client application. + + The message to be transformed into types and handed back to the client application. + Correlation state data. + + + + Inspects a message before a request message is sent to a service. + + The message to be sent to the service. + The client object channel. + + Null since no message correlation is used. + + + + + Gets the singleton instance. + + + + + Naming convention for the request's Response DTO + + + + + Shortcut to get the ResponseStatus whether it's bare or inside a IHttpResult + + + + + + diff --git a/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/sl5/ServiceStack.Client.dll b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/sl5/ServiceStack.Client.dll new file mode 100644 index 00000000..51628a91 Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Client.4.0.11/lib/sl5/ServiceStack.Client.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/ServiceStack.Common.4.0.11.nupkg b/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/ServiceStack.Common.4.0.11.nupkg new file mode 100644 index 00000000..050eb691 Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/ServiceStack.Common.4.0.11.nupkg differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.dll b/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.dll new file mode 100644 index 00000000..4c7a5afb Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.xml b/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.xml new file mode 100644 index 00000000..109d91cf --- /dev/null +++ b/src/Backbone.Todos/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.xml @@ -0,0 +1,206 @@ + + + + ServiceStack.Common + + + + + Useful .NET Encryption Utils from: + http://andrewlocatelliwoodcock.com/2011/08/01/implementing-rsa-asymmetric-public-private-key-encryption-in-c-encrypting-under-the-public-key/ + + + + + Encrypt an arbitrary string of data under the supplied public key + + The public key to encrypt under + The data to encrypt + The bit length or strength of the public key: 1024, 2048 or 4096 bits. This must match the + value actually used to create the publicKey + + + + + Create Public and Private Key Pair based on settings already in static class. + + RsaKeyPair + + + + Gets the textual description of the enum if it has one. e.g. + + + enum UserColors + { + [Description("Bright Red")] + BrightRed + } + UserColors.BrightRed.ToDescription(); + + + + + + + + Creates a Console Logger, that logs all messages to: System.Console + + Made public so its testable + + + + + Default logger is to Console.WriteLine + + Made public so its testable + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + + + + Useful IPAddressExtensions from: + http://blogs.msdn.com/knom/archive/2008/12/31/ip-address-calculations-with-c-subnetmasks-networks.aspx + + + + + + Gets the ipv4 addresses from all Network Interfaces that have Subnet masks. + + + + + + Gets the ipv6 addresses from all Network Interfaces. + + + + + + Func to get the Strongly-typed field + + + + + Required to cast the return ValueType to an object for caching + + + + + Func to set the Strongly-typed field + + + + + Required to cast the ValueType to an object for caching + + + + + Required to cast the ValueType to an object for caching + + + + + Func to get the Strongly-typed field + + + + + Required to cast the return ValueType to an object for caching + + + + + Func to set the Strongly-typed field + + + + + Required to cast the ValueType to an object for caching + + + + + Required to cast the ValueType to an object for caching + + + + + Common functionality when creating adapters + + + + + Executes the specified expression. + + + The action. + + + + + Executes the specified action (for void methods). + + The action. + + + + Note: InMemoryLog keeps all logs in memory, so don't use it long running exceptions + + Returns a thread-safe InMemoryLog which you can use while *TESTING* + to provide a detailed analysis of your logs. + + + + + Creates a Unified Resource Name (URN) with the following formats: + + - urn:{TypeName}:{IdFieldValue} e.g. urn:UserSession:1 + - urn:{TypeName}:{IdFieldName}:{IdFieldValue} e.g. urn:UserSession:UserId:1 + + + + + + + Provide the an option for the callee to block until all commands are executed + + + + + + + Invokes the action provided and returns true if no excpetion was thrown. + Otherwise logs the exception and returns false if an exception was thrown. + + The action. + + + + diff --git a/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/ServiceStack.Interfaces.4.0.11.nupkg b/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/ServiceStack.Interfaces.4.0.11.nupkg new file mode 100644 index 00000000..4e4fca5b Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/ServiceStack.Interfaces.4.0.11.nupkg differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.dll b/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.dll new file mode 100644 index 00000000..d13fea94 Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.xml b/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.xml new file mode 100644 index 00000000..fd6b0866 --- /dev/null +++ b/src/Backbone.Todos/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.xml @@ -0,0 +1,1685 @@ + + + + ServiceStack.Interfaces + + + + + Required when using a TypeDescriptor to make it unique + + + + + A common interface implementation that is implemented by most cache providers + + + + + Removes the specified item from the cache. + + The identifier for the item to delete. + + true if the item was successfully removed from the cache; false otherwise. + + + + + Removes the cache for all the keys provided. + + The keys. + + + + Retrieves the specified item from the cache. + + + The identifier for the item to retrieve. + + The retrieved item, or null if the key was not found. + + + + + Increments the value of the specified key by the given amount. + The operation is atomic and happens on the server. + A non existent value at key starts at 0 + + The identifier for the item to increment. + The amount by which the client wants to increase the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Increments the value of the specified key by the given amount. + The operation is atomic and happens on the server. + A non existent value at key starts at 0 + + The identifier for the item to increment. + The amount by which the client wants to decrease the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Adds a new item into the cache at the specified cache key only if the cache is empty. + + The key used to reference the item. + The object to be inserted into the cache. + + true if the item was successfully stored in the cache; false otherwise. + + The item does not expire unless it is removed due memory pressure. + + + + Sets an item into the cache at the cache key specified regardless if it already exists or not. + + + + + Replaces the item at the cachekey specified only if an items exists at the location already. + + + + + Invalidates all data on the cache. + + + + + Retrieves multiple items from the cache. + The default value of T is set for all keys that do not exist. + + The list of identifiers for the items to retrieve. + + a Dictionary holding all items indexed by their key. + + + + + Sets multiple items to the cache. + + + The values. + + + + Removes items from cache that have keys matching the specified wildcard pattern + + The wildcard, where "*" means any sequence of characters and "?" means any single character. + + + + Removes items from the cache based on the specified regular expression pattern + + Regular expression pattern to search cache keys + + + + A light interface over a cache client. + This interface was inspired by Enyim.Caching.MemcachedClient + + Only the methods that are intended to be used are required, if you require + extra functionality you can uncomment the unused methods below as they have been + implemented in DdnMemcachedClient + + + + + Removes the specified item from the cache. + + The identifier for the item to delete. + + true if the item was successfully removed from the cache; false otherwise. + + + + + Removes the cache for all the keys provided. + + The keys. + + + + Retrieves the specified item from the cache. + + The identifier for the item to retrieve. + + The retrieved item, or null if the key was not found. + + + + + Increments the value of the specified key by the given amount. The operation is atomic and happens on the server. + + The identifier for the item to increment. + The amount by which the client wants to increase the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Increments the value of the specified key by the given amount. The operation is atomic and happens on the server. + + The identifier for the item to increment. + The amount by which the client wants to decrease the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Inserts an item into the cache with a cache key to reference its location. + + The key used to reference the item. + The object to be inserted into the cache. + + true if the item was successfully stored in the cache; false otherwise. + + The item does not expire unless it is removed due memory pressure. + + + + Inserts an item into the cache with a cache key to reference its location. + + The key used to reference the item. + The object to be inserted into the cache. + The time when the item is invalidated in the cache. + true if the item was successfully stored in the cache; false otherwise. + + + + Removes all data from the cache. + + + + + Retrieves multiple items from the cache. + + The list of identifiers for the items to retrieve. + + a Dictionary holding all items indexed by their key. + + + + + A Users Session + + + + + Set a typed value at key + + + + + + + + Get a typed value at key + + + + + + + + Store any object at key + + + + + + + Retrieves a User Session + + + + + Gets the session for this request, creates one if it doesn't exist. + + + + + + + + Gets the session for this request, creates one if it doesn't exist. + Only for ASP.NET apps. Uses the HttpContext.Current singleton. + + + + + Allow delegation of dependencies to other IOC's + + + + + Resolve Property Dependency + + + + + + + Resolve Constructor Dependency + + + + + + + BelongToAttribute + Use to indicate that a join column belongs to another table. + + + + + Compute attribute. + Use to indicate that a property is a Calculated Field + + + + + Decimal length attribute. + + + + + Explicit foreign key name. If it's null, or empty, the FK name will be autogenerated as before. + + + + + IgnoreAttribute + Use to indicate that a property is not a field in the table + properties with this attribute are ignored when building sql sentences + + + + + Primary key attribute. + use to indicate that property is part of the pk + + + + + Used to annotate an Entity with its DB schema + + + + + + For providers that want a cleaner API with a little more perf + + + + + + Decorate any type or property with adhoc info + + + + + Creates a Debug Logger, that logs all messages to: System.Diagnostics.Debug + + Made public so its testable + + + + + Factory to create ILog instances + + + + + Gets the logger. + + + + + Gets the logger. + + + + + Default logger is to System.Diagnostics.Debug.WriteLine + + Made public so its testable + + + + + Logs a message in a running application + + + + + Logs a Debug message. + + The message. + + + + Logs a Debug message and exception. + + The message. + The exception. + + + + Logs a Debug format message. + + The format. + The args. + + + + Logs a Error message. + + The message. + + + + Logs a Error message and exception. + + The message. + The exception. + + + + Logs a Error format message. + + The format. + The args. + + + + Logs a Fatal message. + + The message. + + + + Logs a Fatal message and exception. + + The message. + The exception. + + + + Logs a Error format message. + + The format. + The args. + + + + Logs an Info message and exception. + + The message. + + + + Logs an Info message and exception. + + The message. + The exception. + + + + Logs an Info format message. + + The format. + The args. + + + + Logs a Warning message. + + The message. + + + + Logs a Warning message and exception. + + The message. + The exception. + + + + Logs a Warning format message. + + The format. + The args. + + + + Gets or sets a value indicating whether this instance is debug enabled. + + + true if this instance is debug enabled; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + + + + Default logger is to System.Diagnostics.Debug.Print + + Made public so its testable + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + + + + Creates a Debug Logger, that logs all messages to: System.Diagnostics.Debug + + Made public so its testable + + + + + StringBuilderLog writes to shared StringBuffer. + Made public so its testable + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + The message. + + + + Creates a test Logger, that stores all log messages in a member list + + + + + Tests logger which stores all log messages in a member list which can be examined later + + Made public so its testable + + + + + Initializes a new instance of the class. + + The type. + + + + Initializes a new instance of the class. + + The type. + + + + Logs the specified message. + + The message. + The exception. + + + + Logs the format. + + The message. + The args. + + + + Logs the specified message. + + The message. + + + + Contract indication that the Response DTO has a ResponseStatus + + + + + Logging API for this library. You can inject your own implementation otherwise + will use the DebugLogFactory to write to System.Diagnostics.Debug + + + + + Gets the logger. + + + + + Gets the logger. + + + + + Gets or sets the log factory. + Use this to override the factory that is used to create loggers + + + + + Publish the specified message into the durable queue @queueName + + + + + Publish the specified message into the transient queue @queueName + + + + + Synchronous blocking get. + + + + + Non blocking get message + + + + + Acknowledge the message has been successfully received or processed + + + + + Negative acknowledgement the message was not processed correctly + + + + + Create a typed message from a raw MQ Response artefact + + + + + Simple definition of an MQ Host + + + + + Register DTOs and hanlders the MQ Host will process + + + + + + + Register DTOs and hanlders the MQ Host will process + + + + + + + + Get Total Current Stats for all Message Handlers + + + + + + Get the status of the service. Potential Statuses: Disposed, Stopped, Stopping, Starting, Started + + + + + + Get a Stats dump + + + + + + Start the MQ Host if not already started. + + + + + Stop the MQ Host if not already stopped. + + + + + Factory to create consumers and producers that work with this service + + + + + Get a list of all message types registered on this MQ Host + + + + + Basic implementation of IMessage[T] + + + + + + Util static generic class to create unique queue names for types + + + + + + Util class to create unique queue names for runtime types + + + + + For messaging exceptions that should by-pass the messaging service's configured + retry attempts and store the message straight into the DLQ + + + + + Wrap the common redis list operations under a IList[string] interface. + + + + + Redis transaction for typed client + + + + + + interface to queueable operation using typed redis client + + + + + + Interface to redis typed pipeline + + + + + Pipeline interface shared by typed and non-typed pipelines + + + + + Interface to operations that allow queued commands to be completed + + + + + Returns a high-level typed client API + + + + + + Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly client using the hosts defined in ReadOnlyHosts. + + + + + + Returns a Read/Write ICacheClient (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly ICacheClient using the hosts defined in ReadOnlyHosts. + + + + + + Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly client using the hosts defined in ReadOnlyHosts. + + + + + + Returns a Read/Write ICacheClient (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly ICacheClient using the hosts defined in ReadOnlyHosts. + + + + + + Subscribe to channels by name + + + + + + Subscribe to channels matching the supplied patterns + + + + + + The number of active subscriptions this client has + + + + + Registered handler called after client *Subscribes* to each new channel + + + + + Registered handler called when each message is received + + + + + Registered handler called when each channel is unsubscribed + + + + + Interface to redis transaction + + + + + Base transaction interface, shared by typed and non-typed transactions + + + + + interface to operation that can queue commands + + + + + Interface to redis pipeline + + + + + Gets or sets parameter name with which allowable values will be associated. + + + + + The overall description of an API. Used by Swagger. + + + + + Gets or sets verb to which applies attribute. By default applies to all verbs. + + + + + Gets or sets parameter type: It can be only one of the following: path, query, body, or header. + + + + + Gets or sets unique name for the parameter. Each name must be unique, even if they are associated with different paramType values. + + + + Other notes on the name field: + If paramType is body, the name is used only for UI and codegeneration. + If paramType is path, the name field must correspond to the associated path segment from the path field in the api object. + If paramType is query, the name field corresponds to the query param name. + + + + + + Gets or sets the human-readable description for the parameter. + + + + + For path, query, and header paramTypes, this field must be a primitive. For body, this can be a complex or container datatype. + + + + + For path, this is always true. Otherwise, this field tells the client whether or not the field must be supplied. + + + + + For query params, this specifies that a comma-separated list of values can be passed to the API. For path and body types, this field cannot be true. + + + + + The status code of a response + + + + + The description of a response status code + + + + + Marker interfaces + + + + + Implement on Request DTOs that need access to the raw Request Stream + + + + + The raw Http Request Input Stream + + + + + Resolve a dependency from the AppHost's IOC + + + + + + + This interface can be implemented by an attribute + which adds an request filter for the specific request DTO the attribute marked. + + + + + The request filter is executed before the service. + + The http request wrapper + The http response wrapper + The request DTO + + + + A new shallow copy of this filter is used on every request. + + + + + + Order in which Request Filters are executed. + <0 Executed before global request filters + >0 Executed after global request filters + + + + + This interface can be implemented by an attribute + which adds an response filter for the specific response DTO the attribute marked. + + + + + The response filter is executed after the service + + The http request wrapper + The http response wrapper + + + + A new shallow copy of this filter is used on every request. + + + + + + Order in which Response Filters are executed. + <0 Executed before global response filters + >0 Executed after global response filters + + + + + The HTTP Response Status + + + + + The HTTP Response Status Code + + + + + The HTTP Status Description + + + + + The HTTP Response ContentType + + + + + Additional HTTP Headers + + + + + Response DTO + + + + + if not provided, get's injected by ServiceStack + + + + + Holds the request call context + + + + + A thin wrapper around ASP.NET or HttpListener's HttpRequest + + + + + A thin wrapper around each host's Request e.g: ASP.NET, HttpListener, MQ, etc + + + + + The entire string contents of Request.InputStream + + + + + + The underlying ASP.NET or HttpListener HttpRequest + + + + + The name of the service being called (e.g. Request DTO Name) + + + + + The Verb / HttpMethod or Action for this request + + + + + Optional preferences for the processing of this Request + + + + + The Request DTO, after it has been deserialized. + + + + + The request ContentType + + + + + The expected Response ContentType for this request + + + + + Whether the ResponseContentType has been explicitly overrided or whether it was just the default + + + + + Attach any data to this request that all filters and services can access. + + + + + Buffer the Request InputStream so it can be re-read + + + + + The Remote Ip as reported by Request.UserHostAddress + + + + + The Remote Ip as reported by X-Forwarded-For, X-Real-IP or Request.UserHostAddress + + + + + e.g. is https or not + + + + + Access to the multi-part/formdata files posted on this request + + + + + The value of the Referrer, null if not available + + + + + The HttpResponse + + + + + The HTTP Verb + + + + + The IP Address of the X-Forwarded-For header, null if null or empty + + + + + The Port number of the X-Forwarded-Port header, null if null or empty + + + + + The http or https scheme of the X-Forwarded-Proto header, null if null or empty + + + + + The value of the X-Real-IP header, null if null or empty + + + + + A thin wrapper around ASP.NET or HttpListener's HttpResponse + + + + + A thin wrapper around each host's Response e.g: ASP.NET, HttpListener, MQ, etc + + + + + Signal that this response has been handled and no more processing should be done. + When used in a request or response filter, no more filters or processing is done on this request. + + + + + Calls Response.End() on ASP.NET HttpResponse otherwise is an alias for Close(). + Useful when you want to prevent ASP.NET to provide it's own custom error page. + + + + + Response.Flush() and OutputStream.Flush() seem to have different behaviour in ASP.NET + + + + + The underlying ASP.NET or HttpListener HttpResponse + + + + + The Response DTO + + + + + Gets a value indicating whether this instance is closed. + + + + + Log every service request + + + + + Log a request + + The RequestContext + Request DTO + Response DTO or Exception + How long did the Request take + + + + View the most recent logs + + + + + + + Turn On/Off Session Tracking + + + + + Turn On/Off Raw Request Body Tracking + + + + + Turn On/Off Tracking of Responses + + + + + Turn On/Off Tracking of Exceptions + + + + + Limit access to /requestlogs service to role + + + + + Don't log requests of these types. + + + + + Don't log request bodys for services with sensitive information. + By default Auth and Registration requests are hidden. + + + + + Implement on services that need access to the RequestContext + + + + + Responsible for executing the operation within the specified context. + + The operation types. + + + + Returns the first matching RestPath + + + + + Executes the MQ DTO request. + + + + + Executes the MQ DTO request with the supplied requestContext + + + + + Executes the DTO request under the supplied requestContext. + + + + + Executes the DTO request with an empty RequestContext. + + + + + Allow the registration of user-defined routes for services + + + + + Maps the specified REST path to the specified request DTO. + + The type of request DTO to map + the path to. + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + The same instance; + never . + + + + Maps the specified REST path to the specified request DTO, and + specifies the HTTP verbs supported by the path. + + The type of request DTO to map + the path to. + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + + The comma-delimited list of HTTP verbs supported by the path, + such as "GET,PUT,DELETE". Specify empty or + to indicate that all verbs are supported. + + The same instance; + never . + + + + Maps the specified REST path to the specified request DTO, + specifies the HTTP verbs supported by the path, and indicates + the default MIME type of the returned response. + + + The type of request DTO to map the path to. + + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + + The comma-delimited list of HTTP verbs supported by the path, + such as "GET,PUT,DELETE". + + The same instance; + never . + + + + Maps the specified REST path to the specified request DTO, + specifies the HTTP verbs supported by the path, and indicates + the default MIME type of the returned response. + + + Used to rank the precedences of route definitions in reverse routing. + i.e. Priorities below 0 are auto-generated have less precedence. + + + + + Maps the specified REST path to the specified request DTO, + specifies the HTTP verbs supported by the path, and indicates + the default MIME type of the returned response. + + + The type of request DTO to map the path to. + + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + + The comma-delimited list of HTTP verbs supported by the path, + such as "GET,PUT,DELETE". + + + The short summary of what the REST does. + + + The longer text to explain the behaviour of the REST. + + The same instance; + never . + + + + Used to decorate Request DTO's to associate a RESTful request + path mapping with a service. Multiple attributes can be applied to + each request DTO, to map multiple paths to the service. + + + + + Initializes an instance of the class. + + + The path template to map to the request. See + RouteAttribute.Path + for details on the correct format. + + + + + Initializes an instance of the class. + + + The path template to map to the request. See + RouteAttribute.Path + for details on the correct format. + + A comma-delimited list of HTTP verbs supported by the + service. If unspecified, all verbs are assumed to be supported. + + + + Gets or sets the path template to be mapped to the request. + + + A value providing the path mapped to + the request. Never . + + + Some examples of valid paths are: + + + "/Inventory" + "/Inventory/{Category}/{ItemId}" + "/Inventory/{ItemPath*}" + + + Variables are specified within "{}" + brackets. Each variable in the path is mapped to the same-named property + on the request DTO. At runtime, ServiceStack will parse the + request URL, extract the variable values, instantiate the request DTO, + and assign the variable values into the corresponding request properties, + prior to passing the request DTO to the service object for processing. + + It is not necessary to specify all request properties as + variables in the path. For unspecified properties, callers may provide + values in the query string. For example: the URL + "http://services/Inventory?Category=Books&ItemId=12345" causes the same + request DTO to be processed as "http://services/Inventory/Books/12345", + provided that the paths "/Inventory" (which supports the first URL) and + "/Inventory/{Category}/{ItemId}" (which supports the second URL) + are both mapped to the request DTO. + + Please note that while it is possible to specify property values + in the query string, it is generally considered to be less RESTful and + less desirable than to specify them as variables in the path. Using the + query string to specify property values may also interfere with HTTP + caching. + + The final variable in the path may contain a "*" suffix + to grab all remaining segments in the path portion of the request URL and assign + them to a single property on the request DTO. + For example, if the path "/Inventory/{ItemPath*}" is mapped to the request DTO, + then the request URL "http://services/Inventory/Books/12345" will result + in a request DTO whose ItemPath property contains "Books/12345". + You may only specify one such variable in the path, and it must be positioned at + the end of the path. + + + + + Gets or sets short summary of what the route does. + + + + + Gets or sets longer text to explain the behaviour of the route. + + + + + Gets or sets a comma-delimited list of HTTP verbs supported by the service, such as + "GET,PUT,POST,DELETE". + + + A providing a comma-delimited list of HTTP verbs supported + by the service, or empty if all verbs are supported. + + + + + Used to rank the precedences of route definitions in reverse routing. + i.e. Priorities below 0 are auto-generated have less precedence. + + + + + Fallback routes have the lowest precedence, i.e. after normal Routes, static files or any matching Catch All Handlers. + + + + + Generic ResponseStatus for when Response Type can't be inferred. + In schemaless formats like JSON, JSV it has the same shape as a typed Response DTO + + + + + A log entry added by the IRequestLogger + + + + + Decorate on Request DTO's to alter the accessibility of a service and its visibility on /metadata pages + + + + + Restrict access and metadata visibility to any of the specified access scenarios + + The restrict access to scenarios. + + + + Restrict access and metadata visibility to any of the specified access scenarios + + The restrict access to scenarios. + + + + Returns the allowed set of scenarios based on the user-specified restrictions + + + + + + + Allow access but hide from metadata to requests from Localhost only + + + + + Allow access but hide from metadata to requests from Localhost and Local Intranet only + + + + + Restrict access and hide from metadata to requests from Localhost and Local Intranet only + + + + + Restrict access and hide from metadata to requests from Localhost only + + + + + Sets a single access restriction + + Restrict Access to. + + + + Restrict access to any of the specified access scenarios + + Access restrictions + + + + Sets a single metadata Visibility restriction + + Restrict metadata Visibility to. + + + + Restrict metadata visibility to any of the specified access scenarios + + Visibility restrictions + + + + Converts from a User intended restriction to a flag with all the allowed attribute flags set, e.g: + + If No Network restrictions were specified all Network access types are allowed, e.g: + restrict EndpointAttributes.None => ... 111 + + If a Network restriction was specified, only it will be allowed, e.g: + restrict EndpointAttributes.LocalSubnet => ... 010 + + The returned Enum will have a flag with all the allowed attributes set + + + + + + + Error information pertaining to a particular named field. + Used for returning multiple field validation errors.s + + + + + Common ResponseStatus class that should be present on all response DTO's + + + + + Initializes a new instance of the class. + + A response status without an errorcode == success + + + + + Initializes a new instance of the class. + + A response status with an errorcode == failure + + + + + Initializes a new instance of the class. + + A response status with an errorcode == failure + + + + + Holds the custom ErrorCode enum if provided in ValidationException + otherwise will hold the name of the Exception type, e.g. typeof(Exception).Name + + A value of non-null means the service encountered an error while processing the request. + + + + + A human friendly error message + + + + + + + + + + For multiple detailed validation errors. + Can hold a specific error message for each named field. + + + + + Write a partial content result + + + + + Whether this HttpResult allows Partial Response + + + + + Sends the specified request. + + The request. + + + + diff --git a/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/ServiceStack.Redis.4.0.11.nupkg b/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/ServiceStack.Redis.4.0.11.nupkg new file mode 100644 index 00000000..7df7840d Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/ServiceStack.Redis.4.0.11.nupkg differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/lib/net40/ServiceStack.Redis.XML b/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/lib/net40/ServiceStack.Redis.XML new file mode 100644 index 00000000..2cfb309b --- /dev/null +++ b/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/lib/net40/ServiceStack.Redis.XML @@ -0,0 +1,1281 @@ + + + + ServiceStack.Redis + + + + + Provides thread-safe retrievel of redis clients since each client is a new one. + Allows the configuration of different ReadWrite and ReadOnly hosts + + + BasicRedisClientManager for ICacheClient + + For more interoperabilty I'm also implementing the ICacheClient on + this cache client manager which has the affect of calling + GetCacheClient() for all write operations and GetReadOnlyCacheClient() + for the read ones. + + This works well for master-slave replication scenarios where you have + 1 master that replicates to multiple read slaves. + + + + + Hosts can be an IP Address or Hostname in the format: host[:port] + e.g. 127.0.0.1:6379 + default is: localhost:6379 + + The write hosts. + The read hosts. + + + + Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly client using the hosts defined in ReadOnlyHosts. + + + + + + Gets or sets object key prefix. + + + + + Courtesy of @marcgravell + http://code.google.com/p/protobuf-net/source/browse/trunk/protobuf-net/BufferPool.cs + + + + + A complete redis command, with method to send command, receive response, and run callback on success or failure + + + + + Allows you to get Redis value operations to operate against POCO types. + + + + + + Use this to share the same redis connection with another + + The client. + + + + Pipeline for redis typed client + + + + + + Queue of commands for redis typed client + + + + + + Redis operation (transaction/pipeline) that allows queued commands to be completed + + + + + Ignore dispose on RedisClientsManager, which should be registered as a singleton + + + + + Useful wrapper IRedisClientsManager to cut down the boiler plat of most IRedisClient access + + + + + A complete redis command, with method to send command, receive response, and run callback on success or failure + + + + + Redis command that does not get queued + + + + + The client wraps the native redis operations into a more readable c# API. + + Where possible these operations are also exposed in common c# interfaces, + e.g. RedisClient.Lists => IList[string] + RedisClient.Sets => ICollection[string] + + + + + This class contains all the common operations for the RedisClient. + The client contains a 1:1 mapping of c# methods to redis operations of the same name. + + Not threadsafe use a pooled manager + + + + + Requires custom result parsing + + Number of results + + + + Command to set multuple binary safe arguments + + + + + + + reset buffer index in send buffer + + + + + Used to manage connection pooling + + + + + Gets or sets object key prefix. + + + + + Creates a new instance of the Redis Client from NewFactoryFn. + + + + + Returns key with automatic object id detection in provided value with generic type. + + + + + + + Returns key with explicit object id. + + + + + + + Returns key with explicit object type and id. + + + + + + + + Provides a redis connection pool that can be sharded + + + + + For interoperabilty GetCacheClient() and GetReadOnlyCacheClient() + return an ICacheClient wrapper around the redis manager which has the affect of calling + GetClient() for all write operations and GetReadOnlyClient() for the read ones. + + This works well for master-slave replication scenarios where you have + 1 master that replicates to multiple read slaves. + + + Provides thread-safe pooling of redis client connections. + Allows load-balancing of master-write and read-slave hosts, ideal for + 1 master and multiple replicated read slaves. + + + + + Hosts can be an IP Address or Hostname in the format: host[:port] + e.g. 127.0.0.1:6379 + default is: localhost:6379 + + The write hosts. + The read hosts. + The config. + + + + Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts + + + + + + Called within a lock + + + + + + Returns a ReadOnly client using the hosts defined in ReadOnlyHosts. + + + + + + Called within a lock + + + + + + Disposes the read only client. + + The client. + + + + Disposes the write client. + + The client. + + + + Gets or sets object key prefix. + + + + + Manage a client acquired from the PooledRedisClientManager + Dispose method will release the client back to the pool. + + + + + wrap the acquired client + + + + + + release the wrapped client back to the pool + + + + + access the wrapped client + + + + + logical name + + + + + An arbitrary weight relative to other nodes + + + + logical name + An arbitrary weight relative to other nodes + redis nodes + + + + Provides sharding of redis client connections. + uses consistent hashing to distribute keys across connection pools + + + + + maps a key to a redis connection pool + + key to map + a redis connection pool + + + + Adds a node and maps points across the circle + + node to add + An arbitrary number, specifies how often it occurs relative to other targets. + + + + A variation of Binary Search algorithm. Given a number, matches the next highest number from the sorted array. + If a higher number does not exist, then the first number in the array is returned. + + a sorted array to perform the search + number to find the next highest number against + next highest number + + + + Given a key, generates an unsigned 64 bit hash code using MD5 + + + + + + + Distributed lock interface + + + + + Optimized implementation. Primitive types are manually serialized, the rest are serialized using binary serializer />. + + + + + serialize/deserialize arbitrary objects + (objects must be serializable) + + + + + Serialize object to buffer + + serializable object + + + + + Deserialize buffer to object + + byte array to deserialize + + + + + + + + + + + + + + + + + + + serialize value and wrap with + + + + + + + Unwrap object wrapped in + + + + + + + pop numProcessed items from queue and unlock queue for work item id that dequeued + items are associated with + + + + + + A dequeued work item has been processed. When all of the dequeued items have been processed, + all items will be popped from the queue,and the queue unlocked for the work item id that + the dequeued items are associated with + + + + + Update first unprocessed item with new work item. + + + + + + + + + + + distributed work item queue. Each message must have an associated + work item id. For a given id, all work items are guaranteed to be processed + in the order in which they are received. + + + + + distributed work item queue. Each message must have an associated + work item id. For a given id, all work items are guaranteed to be processed + in the order in which they are received. + + + + + + + distributed work item queue + + + + + Enqueue item in priority queue corresponding to workItemId identifier + + + + + + + Preprare next work item id for dequeueing + + + + + Dequeue up to maxBatchSize items from queue corresponding to workItemId identifier. + Once this method is called, or will not + return any items for workItemId until the dequeue lock returned is unlocked. + + + + + + + + Replace existing work item in workItemId queue + + + + + + + + Queue incoming messages + + + + + + + Must call this periodically to move work items from priority queue to pending queue + + + + + Replace existing work item in workItemId queue + + + + + + + + Pop items from list + + + + + + + Force release of locks held by crashed servers + + + + + release lock held by crashed server + + + + true if lock is released, either by this method or by another client; false otherwise + + + + Unlock work item id, so other servers can process items for this id + + + + + + + + + + + + + + + + + + + + + + + + + + + pop remaining items that were returned by dequeue, and unlock queue + + + + + + indicate that an item has been processed by the caller + + + + + Update first unprocessed work item + + + + + + wraps a serialized representation of an object + + + + + + Initializes a new instance of . + + Custom item data. + The serialized item. + + + + The data representing the item being stored/retireved. + + + + + Flags set for this instance. + + + + + distributed lock class that follows the Resource Allocation Is Initialization pattern + + + + + Lock + + + + in seconds + in seconds + + + + unlock + + + + + Enqueue item + + + + + + Dequeue up to maxBatchSize items from queue + + + + + + + distributed work item queue. Messages are processed in chronological order + + + + + Enqueue incoming messages + + + + + + + + Dequeue next batch of work items + + + + + + + + + simple distributed work item queue + + + + + + + Queue incoming messages + + + + + + Dequeue next batch of work items for processing. After this method is called, + no other work items with same id will be available for + dequeuing until PostDequeue is called + + KeyValuePair: key is work item id, and value is list of dequeued items. + + + + + Serialize object to buffer + + serializable object + + + + + + + array of serializable objects + + + + + Deserialize buffer to object + + byte array to deserialize + + + + + + customize the client serializer + + + + + Factory to create SerializingRedisClient objects + + + + + + + + + General purpose pipeline + + + + + + Flush send buffer, and read responses + + + + + Wrap the common redis set operations under a ICollection[string] interface. + + + + + Adds support for Redis Transactions (i.e. MULTI/EXEC/DISCARD operations). + + + + + Put "QUEUED" messages at back of queue + + + + + + Issue exec command (not queued) + + + + + callback for after result count is read in + + + + + + Wrap the common redis set operations under a ICollection[string] interface. + + + + + Wrap the common redis set operations under a ICollection[string] interface. + + + + + Wrap the common redis set operations under a ICollection[string] interface. + + + + + Redis-specific exception. Thrown if unable to connect to Redis server due to socket exception, for example. + + + + + Adds support for Redis Transactions (i.e. MULTI/EXEC/DISCARD operations). + + + + + Put "QUEUED" messages at back of queue + + + + + + Issue exec command (not queued) + + + + + callback for after result count is read in + + + + + + Provide the default factory implementation for creating a RedisClient that + can be mocked and used by different 'Redis Client Managers' + + + + + Wrap the common redis set operations under a ICollection[string] interface. + + + + + Provide the factory implementation for creating a RedisCacheClient that + can be mocked and used by different 'Redis Client Managers' + + + + + Wrap the common redis set operations under a ICollection[string] interface. + + + + + Wrap the common redis list operations under a IList[string] interface. + + + + + Represents a generic collection of key/value pairs that are ordered independently of the key and value. + + The type of the keys in the dictionary + The type of the values in the dictionary + + + + Adds an entry with the specified key and value into the IOrderedDictionary<TKey,TValue> collection with the lowest available index. + + The key of the entry to add. + The value of the entry to add. + The index of the newly added entry + + You can also use the property to add new elements by setting the value of a key that does not exist in the IOrderedDictionary<TKey,TValue> collection; however, if the specified key already exists in the IOrderedDictionary<TKey,TValue>, setting the property overwrites the old value. In contrast, the method does not modify existing elements. + An element with the same key already exists in the IOrderedDictionary<TKey,TValue> + The IOrderedDictionary<TKey,TValue> is read-only.
    + -or-
    + The IOrderedDictionary<TKey,TValue> has a fized size.
    +
    + + + Inserts a new entry into the IOrderedDictionary<TKey,TValue> collection with the specified key and value at the specified index. + + The zero-based index at which the element should be inserted. + The key of the entry to add. + The value of the entry to add. The value can be if the type of the values in the dictionary is a reference type. + is less than 0.
    + -or-
    + is greater than .
    + An element with the same key already exists in the IOrderedDictionary<TKey,TValue>. + The IOrderedDictionary<TKey,TValue> is read-only.
    + -or-
    + The IOrderedDictionary<TKey,TValue> has a fized size.
    +
    + + + Gets or sets the value at the specified index. + + The zero-based index of the value to get or set. + The value of the item at the specified index. + is less than 0.
    + -or-
    + is equal to or greater than .
    +
    + + + Represents a generic collection of key/value pairs that are ordered independently of the key and value. + + The type of the keys in the dictionary + The type of the values in the dictionary + + + + Initializes a new instance of the OrderedDictionary<TKey,TValue> class. + + + + + Initializes a new instance of the OrderedDictionary<TKey,TValue> class using the specified initial capacity. + + The initial number of elements that the OrderedDictionary<TKey,TValue> can contain. + is less than 0 + + + + Initializes a new instance of the OrderedDictionary<TKey,TValue> class using the specified comparer. + + The IEqualityComparer<TKey> to use when comparing keys, or to use the default EqualityComparer<TKey> for the type of the key. + + + + Initializes a new instance of the OrderedDictionary<TKey,TValue> class using the specified initial capacity and comparer. + + The initial number of elements that the OrderedDictionary<TKey,TValue> collection can contain. + The IEqualityComparer<TKey> to use when comparing keys, or to use the default EqualityComparer<TKey> for the type of the key. + is less than 0 + + + + Converts the object passed as a key to the key type of the dictionary + + The key object to check + The key object, cast as the key type of the dictionary + is . + The key type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of . + + + + Converts the object passed as a value to the value type of the dictionary + + The object to convert to the value type of the dictionary + The value object, converted to the value type of the dictionary + is , and the value type of the OrderedDictionary<TKey,TValue> is a value type. + The value type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of . + + + + Inserts a new entry into the OrderedDictionary<TKey,TValue> collection with the specified key and value at the specified index. + + The zero-based index at which the element should be inserted. + The key of the entry to add. + The value of the entry to add. The value can be if the type of the values in the dictionary is a reference type. + is less than 0.
    + -or-
    + is greater than .
    + is . + An element with the same key already exists in the OrderedDictionary<TKey,TValue>. +
    + + + Inserts a new entry into the OrderedDictionary<TKey,TValue> collection with the specified key and value at the specified index. + + The zero-based index at which the element should be inserted. + The key of the entry to add. + The value of the entry to add. The value can be if the type of the values in the dictionary is a reference type. + is less than 0.
    + -or-
    + is greater than .
    + is .
    + -or-
    + is , and the value type of the OrderedDictionary<TKey,TValue> is a value type.
    + The key type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of .
    + -or-
    + The value type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of .
    + -or-
    + An element with the same key already exists in the OrderedDictionary<TKey,TValue>.
    +
    + + + Removes the entry at the specified index from the OrderedDictionary<TKey,TValue> collection. + + The zero-based index of the entry to remove. + is less than 0.
    + -or-
    + index is equal to or greater than .
    +
    + + + Adds an entry with the specified key and value into the OrderedDictionary<TKey,TValue> collection with the lowest available index. + + The key of the entry to add. + The value of the entry to add. This value can be . + A key cannot be , but a value can be. + You can also use the property to add new elements by setting the value of a key that does not exist in the OrderedDictionary<TKey,TValue> collection; however, if the specified key already exists in the OrderedDictionary<TKey,TValue>, setting the property overwrites the old value. In contrast, the method does not modify existing elements. + is + An element with the same key already exists in the OrderedDictionary<TKey,TValue> + + + + Adds an entry with the specified key and value into the OrderedDictionary<TKey,TValue> collection with the lowest available index. + + The key of the entry to add. + The value of the entry to add. This value can be . + The index of the newly added entry + A key cannot be , but a value can be. + You can also use the property to add new elements by setting the value of a key that does not exist in the OrderedDictionary<TKey,TValue> collection; however, if the specified key already exists in the OrderedDictionary<TKey,TValue>, setting the property overwrites the old value. In contrast, the method does not modify existing elements. + is + An element with the same key already exists in the OrderedDictionary<TKey,TValue> + + + + Adds an entry with the specified key and value into the OrderedDictionary<TKey,TValue> collection with the lowest available index. + + The key of the entry to add. + The value of the entry to add. This value can be . + is .
    + -or-
    + is , and the value type of the OrderedDictionary<TKey,TValue> is a value type.
    + The key type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of .
    + -or-
    + The value type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of .
    +
    + + + Removes all elements from the OrderedDictionary<TKey,TValue> collection. + + The capacity is not changed as a result of calling this method. + + + + Determines whether the OrderedDictionary<TKey,TValue> collection contains a specific key. + + The key to locate in the OrderedDictionary<TKey,TValue> collection. + if the OrderedDictionary<TKey,TValue> collection contains an element with the specified key; otherwise, . + is + + + + Determines whether the OrderedDictionary<TKey,TValue> collection contains a specific key. + + The key to locate in the OrderedDictionary<TKey,TValue> collection. + if the OrderedDictionary<TKey,TValue> collection contains an element with the specified key; otherwise, . + is + The key type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of . + + + + Returns the zero-based index of the specified key in the OrderedDictionary<TKey,TValue> + + The key to locate in the OrderedDictionary<TKey,TValue> + The zero-based index of , if is found in the OrderedDictionary<TKey,TValue>; otherwise, -1 + This method performs a linear search; therefore it has a cost of O(n) at worst. + + + + Removes the entry with the specified key from the OrderedDictionary<TKey,TValue> collection. + + The key of the entry to remove + if the key was found and the corresponding element was removed; otherwise, + + + + Removes the entry with the specified key from the OrderedDictionary<TKey,TValue> collection. + + The key of the entry to remove + + + + Copies the elements of the OrderedDictionary<TKey,TValue> elements to a one-dimensional Array object at the specified index. + + The one-dimensional object that is the destination of the objects copied from the OrderedDictionary<TKey,TValue>. The must have zero-based indexing. + The zero-based index in at which copying begins. + The method preserves the order of the elements in the OrderedDictionary<TKey,TValue> + + + + Gets the value associated with the specified key. + + The key of the value to get. + When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of . This parameter can be passed uninitialized. + if the OrderedDictionary<TKey,TValue> contains an element with the specified key; otherwise, . + + + + Adds the specified value to the OrderedDictionary<TKey,TValue> with the specified key. + + The KeyValuePair<TKey,TValue> structure representing the key and value to add to the OrderedDictionary<TKey,TValue>. + + + + Determines whether the OrderedDictionary<TKey,TValue> contains a specific key and value. + + The KeyValuePair<TKey,TValue> structure to locate in the OrderedDictionary<TKey,TValue>. + if is found in the OrderedDictionary<TKey,TValue>; otherwise, . + + + + Copies the elements of the OrderedDictionary<TKey,TValue> to an array of type , starting at the specified index. + + The one-dimensional array of type KeyValuePair<TKey,TValue> that is the destination of the KeyValuePair<TKey,TValue> elements copied from the OrderedDictionary<TKey,TValue>. The array must have zero-based indexing. + The zero-based index in at which copying begins. + + + + Removes a key and value from the dictionary. + + The KeyValuePair<TKey,TValue> structure representing the key and value to remove from the OrderedDictionary<TKey,TValue>. + if the key and value represented by is successfully found and removed; otherwise, . This method returns if is not found in the OrderedDictionary<TKey,TValue>. + + + + Gets the dictionary object that stores the keys and values + + The dictionary object that stores the keys and values for the OrderedDictionary<TKey,TValue> + Accessing this property will create the dictionary object if necessary + + + + Gets the list object that stores the key/value pairs. + + The list object that stores the key/value pairs for the OrderedDictionary<TKey,TValue> + Accessing this property will create the list object if necessary. + + + + Gets or sets the value at the specified index. + + The zero-based index of the value to get or set. + The value of the item at the specified index. + is less than 0.
    + -or-
    + index is equal to or greater than .
    +
    + + + Gets or sets the value at the specified index. + + The zero-based index of the value to get or set. + The value of the item at the specified index. + is less than 0.
    + -or-
    + index is equal to or greater than .
    + is a null reference, and the value type of the OrderedDictionary<TKey,TValue> is a value type. + The value type of the OrderedDictionary<TKey,TValue> is not in the inheritance hierarchy of . +
    + + + Gets a value indicating whether the OrderedDictionary<TKey,TValue> has a fixed size. + + if the OrderedDictionary<TKey,TValue> has a fixed size; otherwise, . The default is . + + + + Gets a value indicating whether the OrderedDictionary<TKey,TValue> collection is read-only. + + if the OrderedDictionary<TKey,TValue> is read-only; otherwise, . The default is . + + A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created. + A collection that is read-only is simply a collection with a wrapper that prevents modification of the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes. + + + + + Gets an object containing the keys in the OrderedDictionary<TKey,TValue>. + + An object containing the keys in the OrderedDictionary<TKey,TValue>. + The returned object is not a static copy; instead, the collection refers back to the keys in the original OrderedDictionary<TKey,TValue>. Therefore, changes to the OrderedDictionary<TKey,TValue> continue to be reflected in the key collection. + + + + Gets an object containing the values in the OrderedDictionary<TKey,TValue> collection. + + An object containing the values in the OrderedDictionary<TKey,TValue> collection. + The returned object is not a static copy; instead, the refers back to the values in the original OrderedDictionary<TKey,TValue> collection. Therefore, changes to the OrderedDictionary<TKey,TValue> continue to be reflected in the . + + + + Gets or sets the value with the specified key. + + The key of the value to get or set. + The value associated with the specified key. If the specified key is not found, attempting to get it returns , and attempting to set it creates a new element using the specified key. + + + + Gets or sets the value with the specified key. + + The key of the value to get or set. + The value associated with the specified key. If the specified key is not found, attempting to get it returns , and attempting to set it creates a new element using the specified key. + + + + Gets the number of key/values pairs contained in the OrderedDictionary<TKey,TValue> collection. + + The number of key/value pairs contained in the OrderedDictionary<TKey,TValue> collection. + + + + Gets a value indicating whether access to the OrderedDictionary<TKey,TValue> object is synchronized (thread-safe). + + This method always returns false. + + + + Gets an object that can be used to synchronize access to the OrderedDictionary<TKey,TValue> object. + + An object that can be used to synchronize access to the OrderedDictionary<TKey,TValue> object. + + + + Gets an ICollection<TKey> object containing the keys in the OrderedDictionary<TKey,TValue>. + + An ICollection<TKey> object containing the keys in the OrderedDictionary<TKey,TValue>. + The returned ICollection<TKey> object is not a static copy; instead, the collection refers back to the keys in the original OrderedDictionary<TKey,TValue>. Therefore, changes to the OrderedDictionary<TKey,TValue> continue to be reflected in the key collection. + + + + Gets an ICollection<TValue> object containing the values in the OrderedDictionary<TKey,TValue>. + + An ICollection<TValue> object containing the values in the OrderedDictionary<TKey,TValue>. + The returned ICollection<TKey> object is not a static copy; instead, the collection refers back to the values in the original OrderedDictionary<TKey,TValue>. Therefore, changes to the OrderedDictionary<TKey,TValue> continue to be reflected in the value collection. + + + + acquire distributed, non-reentrant lock on key + + global key for this lock + timeout for acquiring lock + timeout for lock, in seconds (stored as value against lock key) + + + + + + unlock key + + + + + + + + + + + + + Locking strategy interface + + + + + This class manages a read lock for a local readers/writer lock, + using the Resource Acquisition Is Initialization pattern + + + + + RAII initialization + + + + + + RAII disposal + + + + + This class manages a write lock for a local readers/writer lock, + using the Resource Acquisition Is Initialization pattern + + + + + + RAII disposal + + + + + manages a "region" in the redis key space + namespace can be cleared by incrementing the generation + + + + + get current generation + + + + + + set new generation + + + + + + redis key for generation + + + + + + get redis key that holds all namespace keys + + + + + + get global cache key + + + + + + + get global key inside of this namespace + + + prefixes can be added for name deconfliction + + + + + replace UniqueCharacter with its double, to avoid name clash + + + + + + + + + + + + + + get locking strategy + + +
    +
    diff --git a/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/lib/net40/ServiceStack.Redis.dll b/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/lib/net40/ServiceStack.Redis.dll new file mode 100644 index 00000000..d7469c0d Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Redis.4.0.11/lib/net40/ServiceStack.Redis.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/ServiceStack.Text.4.0.11.nupkg b/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/ServiceStack.Text.4.0.11.nupkg new file mode 100644 index 00000000..9ff6da54 Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/ServiceStack.Text.4.0.11.nupkg differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.dll b/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.dll new file mode 100644 index 00000000..30eee22c Binary files /dev/null and b/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.dll differ diff --git a/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.xml b/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.xml new file mode 100644 index 00000000..9688d3e1 --- /dev/null +++ b/src/Backbone.Todos/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.xml @@ -0,0 +1,703 @@ + + + + ServiceStack.Text + + + + + Utils to load types + + + + + Find the type from the name supplied + + [typeName] or [typeName, assemblyName] + + + + + The top-most interface of the given type, if any. + + + + + Find type if it exists + + + + The type if it exists + + + + Populate an object with Example data. + + + + + + + Populates the object with example data. + + + Tracks how deeply nested we are + + + + + If AlwaysUseUtc is set to true then convert all DateTime to UTC. + + + + + + + Repairs an out-of-spec XML date/time string which incorrectly uses a space instead of a 'T' to separate the date from the time. + These string are occasionally generated by SQLite and can cause errors in OrmLite when reading these columns from the DB. + + The XML date/time string to repair + The repaired string. If no repairs were made, the original string is returned. + + + + WCF Json format: /Date(unixts+0000)/ + + + + + + + WCF Json format: /Date(unixts+0000)/ + + + + + + + Get the type(string) constructor if exists + + The type. + + + + + micro optimizations: using flags instead of value.IndexOfAny(EscapeChars) + + + + + + + Class to hold + + + + + + A fast, standards-based, serialization-issue free DateTime serailizer. + + + + + Determines whether this serializer can create the specified type from a string. + + The type. + + true if this instance [can create from string] the specified type; otherwise, false. + + + + + Parses the specified value. + + The value. + + + + + Deserializes from reader. + + The reader. + + + + + Serializes to string. + + The value. + + + + + Serializes to writer. + + The value. + The writer. + + + + Sets which format to use when serializing TimeSpans + + + + + if the is configured + to take advantage of specification, + to support user-friendly serialized formats, ie emitting camelCasing for JSON + and parsing member names and enum values in a case-insensitive manner. + + + + + if the is configured + to support web-friendly serialized formats, ie emitting lowercase_underscore_casing for JSON + + + + + Define how property names are mapped during deserialization + + + + + Gets or sets a value indicating if the framework should throw serialization exceptions + or continue regardless of deserialization errors. If the framework + will throw; otherwise, it will parse as many fields as possible. The default is . + + + + + Gets or sets a value indicating if the framework should always convert to UTC format instead of local time. + + + + + Gets or sets a value indicating if the framework should always assume is in UTC format if Kind is Unspecified. + + + + + Gets or sets whether we should append the Utc offset when we serialize Utc dates. Defaults to no. + Only supported for when the JsConfig.DateHandler == JsonDateHandler.TimestampOffset + + + + + Gets or sets a value indicating if unicode symbols should be serialized as "\uXXXX". + + + + + If set to true, Interface types will be prefered over concrete types when serializing. + + + + + Sets the maximum depth to avoid circular dependencies + + + + + Set this to enable your own type construction provider. + This is helpful for integration with IoC containers where you need to call the container constructor. + Return null if you don't know how to construct the type and the parameterless constructor will be used. + + + + + If set to true, Interface types will be prefered over concrete types when serializing. + + + + + Always emit type info for this type. Takes precedence over ExcludeTypeInfo + + + + + Never emit type info for this type + + + + + if the is configured + to take advantage of specification, + to support user-friendly serialized formats, ie emitting camelCasing for JSON + and parsing member names and enum values in a case-insensitive manner. + + + + + Define custom serialization fn for BCL Structs + + + + + Define custom raw serialization fn + + + + + Define custom serialization hook + + + + + Define custom deserialization fn for BCL Structs + + + + + Define custom raw deserialization fn for objects + + + + + Exclude specific properties of this type from being serialized + + + + + Opt-in flag to set some Value Types to be treated as a Ref Type + + + + + Whether there is a fn (raw or otherwise) + + + + + The property names on target types must match property names in the JSON source + + + + + The property names on target types may not match the property names in the JSON source + + + + + Uses the xsd format like PT15H10M20S + + + + + Uses the standard .net ToString method of the TimeSpan class + + + + + Get JSON string value converted to T + + + + + Get JSON string value + + + + + Get unescaped string value + + + + + Get unescaped string value + + + + + Write JSON Array, Object, bool or number values as raw string + + + + + Get JSON string value + + + + + Creates an instance of a Type from a string value + + + + + Parses the specified value. + + The value. + + + + + Shortcut escape when we're sure value doesn't contain any escaped chars + + + + + + + Given a character as utf32, returns the equivalent string provided that the character + is legal json. + + + + + + + micro optimizations: using flags instead of value.IndexOfAny(EscapeChars) + + + + + + + Implement the serializer using a more static approach + + + + + + Implement the serializer using a more static approach + + + + + + Public Code API to register commercial license for ServiceStack. + + + + + Internal Utilities to verify licensing + + + + + Pretty Thread-Safe cache class from: + http://code.google.com/p/dapper-dot-net/source/browse/Dapper/SqlMapper.cs + + This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), + and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE** + equality. The type is fully thread-safe. + + + + + Represents an individual object, allowing access to members by-name + + + + + Use the target types definition of equality + + + + + Obtain the hash of the target object + + + + + Use the target's definition of a string representation + + + + + Wraps an individual object, allowing by-name access to that instance + + + + + Get or Set the value of a named member for the underlying object + + + + + The object represented by this instance + + + + + Provides by-name member-access to objects of a given type + + + + + Create a new instance of this type + + + + + Provides a type-specific accessor, allowing by-name access for all objects of that type + + The accessor is cached internally; a pre-existing accessor may be returned + + + + Does this type support new instances via a parameterless constructor? + + + + + Get or set the value of a named member on the target instance + + + + + Maps the path of a file in the context of a VS project + + the relative path + the absolute path + Assumes static content is two directories above the /bin/ directory, + eg. in a unit test scenario the assembly would be in /bin/Debug/. + + + + Maps the path of a file in a self-hosted scenario + + the relative path + the absolute path + Assumes static content is copied to /bin/ folder with the assemblies + + + + Maps the path of a file in an Asp.Net hosted scenario + + the relative path + the absolute path + Assumes static content is in the parent folder of the /bin/ directory + + + + Implement the serializer using a more static approach + + + + + + Creates a new instance of type. + First looks at JsConfig.ModelFactory before falling back to CreateInstance + + + + + Creates a new instance of type. + First looks at JsConfig.ModelFactory before falling back to CreateInstance + + + + + Creates a new instance from the default constructor of type + + + + + Add a Property attribute at runtime. + Not threadsafe, should only add attributes on Startup. + + + + + Add a Property attribute at runtime. + Not threadsafe, should only add attributes on Startup. + + + + + @jonskeet: Collection of utility methods which operate on streams. + r285, February 26th 2009: http://www.yoda.arachsys.com/csharp/miscutil/ + + + + + Reads the given stream up to the end, returning the data as a byte + array. + + + + + Reads the given stream up to the end, returning the data as a byte + array, using the given buffer size. + + + + + Reads the given stream up to the end, returning the data as a byte + array, using the given buffer for transferring data. Note that the + current contents of the buffer is ignored, so the buffer needn't + be cleared beforehand. + + + + + Copies all the data from one stream into another. + + + + + Copies all the data from one stream into another, using a buffer + of the given size. + + + + + Copies all the data from one stream into another, using the given + buffer for transferring data. Note that the current contents of + the buffer is ignored, so the buffer needn't be cleared beforehand. + + + + + Reads exactly the given number of bytes from the specified stream. + If the end of the stream is reached before the specified amount + of data is read, an exception is thrown. + + + + + Reads into a buffer, filling it completely. + + + + + Reads exactly the given number of bytes from the specified stream, + into the given buffer, starting at position 0 of the array. + + + + + Reads exactly the given number of bytes from the specified stream, + into the given buffer, starting at position 0 of the array. + + + + + Same as ReadExactly, but without the argument checks. + + + + + Converts from base: 0 - 62 + + The source. + From. + To. + + + + + Skip the encoding process for 'safe strings' + + + + + + + A class to allow the conversion of doubles to string representations of + their exact decimal values. The implementation aims for readability over + efficiency. + + Courtesy of @JonSkeet + http://www.yoda.arachsys.com/csharp/DoubleConverter.cs + + + + + + + + How many digits are *after* the decimal point + + + + + Constructs an arbitrary decimal expansion from the given long. + The long must not be negative. + + + + + Multiplies the current expansion by the given amount, which should + only be 2 or 5. + + + + + Shifts the decimal point; a negative value makes + the decimal expansion bigger (as fewer digits come after the + decimal place) and a positive value makes the decimal + expansion smaller. + + + + + Removes leading/trailing zeroes from the expansion. + + + + + Converts the value to a proper decimal string representation. + + + + + Creates an instance of a Type from a string value + + + + + Determines whether the specified type is convertible from string. + + The type. + + true if the specified type is convertible from string; otherwise, false. + + + + + Parses the specified value. + + The value. + + + + + Parses the specified type. + + The type. + The value. + + + + + Useful extension method to get the Dictionary[string,string] representation of any POCO type. + + + + + + Recursively prints the contents of any POCO object in a human-friendly, readable format + + + + + + Print Dump to Console.WriteLine + + + + + Print string.Format to Console.WriteLine + + + + + Parses the specified value. + + The value. + + + + diff --git a/src/Backbone.Todos/packages/repositories.config b/src/Backbone.Todos/packages/repositories.config new file mode 100644 index 00000000..0dec135f --- /dev/null +++ b/src/Backbone.Todos/packages/repositories.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/ConsoleUtil/ConsoleUtil.csproj b/src/ConsoleUtil/ConsoleUtil.csproj new file mode 100644 index 00000000..15345585 --- /dev/null +++ b/src/ConsoleUtil/ConsoleUtil.csproj @@ -0,0 +1,71 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {7E6BF778-F067-41AC-ACB4-AFF0880EC560} + Exe + Properties + ConsoleUtil + ConsoleUtil + v3.5 + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\lib\ServiceStack.dll + + + ..\..\lib\ServiceStack.Text.dll + + + + + + + + + + + + + + + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F} + Docs + + + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF} + Docs.Logic + + + + + \ No newline at end of file diff --git a/src/ConsoleUtil/Program.cs b/src/ConsoleUtil/Program.cs new file mode 100644 index 00000000..fc26607e --- /dev/null +++ b/src/ConsoleUtil/Program.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using System.IO; +using Docs; +using Docs.Logic; +using ServiceStack.Text; + +namespace ConsoleUtil +{ + class Program + { + public static List Pages { get; set; } + + static void Main(string[] args) + { + var filePath = @"C:\src\ServiceStack.Examples\src\Docs\Pages.json"; + if (File.Exists(filePath)) + { + var json = File.ReadAllText(filePath); + Pages = JsonSerializer.DeserializeFromString>(json); + + var webHostUrl = "http://servicestack.net/docs/"; + foreach (var page in Pages) + { + //ReplaceOldLinks(webHostUrl, page); + var contents = page.GetContent(); + contents = contents.Replace(webHostUrl, "~/"); + Save(page, contents); + } + } + } + + public static void ReplaceOldLinks(string baseUrl, Page srcPage) + { + var content = srcPage.GetContent(); + if (content == null) return; + + foreach (var page in Pages) + { + var realSrc = page.Src; + if (realSrc.EndsWith("/wiki/Home")) + realSrc = realSrc.Replace("/wiki/Home", "/wiki"); + else if (realSrc.EndsWith("/blob/master/README.md")) + realSrc = realSrc.Replace("/blob/master/README.md", ""); + + var realSrcLink = "(" + realSrc + ")"; + if (content.IndexOf(realSrcLink) == -1) continue; + + var newUrl = baseUrl + page.Category.SafeName() + "/" + page.Slug; + + var newUrlLink = "(" + newUrl + ")"; + content = content.Replace(realSrcLink, newUrlLink); + } + + content = content.Replace( + "(https://github.com/ServiceStack/ServiceStack.Redis/wiki/Caching)", + "(http://servicestack.net/docs/framework/caching-options)"); + + Save(srcPage, content); + } + + public static void Save(Page srcPage, string contents) + { + var cateogryDir = Path.Combine(@"C:\src\ServiceStack.Examples\src\Docs", srcPage.Category.SafeName()); + + if (!Directory.Exists(cateogryDir)) + Directory.CreateDirectory(cateogryDir); + + srcPage.FilePath = Path.Combine(cateogryDir, srcPage.Slug + ".md"); + File.WriteAllText(srcPage.FilePath, contents); + } + + } + +} diff --git a/src/ConsoleUtil/Properties/AssemblyInfo.cs b/src/ConsoleUtil/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..36ecc743 --- /dev/null +++ b/src/ConsoleUtil/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ConsoleUtil")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ConsoleUtil")] +[assembly: AssemblyCopyright("Copyright © 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c0143a71-3933-4d45-b5f9-957f644ed1cc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Docs/Docs.Logic/CategoryService.cs b/src/Docs/Docs.Logic/CategoryService.cs new file mode 100644 index 00000000..d51c6723 --- /dev/null +++ b/src/Docs/Docs.Logic/CategoryService.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using ServiceStack; + +namespace Docs.Logic +{ + public class Category + { + public string Name { get; set; } + } + + public class CategoryResponse + { + public string Name { get; set; } + + public List Results { get; set; } + } + + public class CategoryService : Service + { + public PageManager PageManager { get; set; } + + public object Get(Category request) + { + List pages = null; + if (!request.Name.IsNullOrEmpty()) + PageManager.CategoriesMap.TryGetValue(request.Name, out pages); + + return new CategoryResponse { + Name = request.Name, + Results = pages ?? new List() + }; + } + } +} \ No newline at end of file diff --git a/src/Docs/Docs.Logic/CustomMarkdownPage.cs b/src/Docs/Docs.Logic/CustomMarkdownPage.cs new file mode 100644 index 00000000..da8e5036 --- /dev/null +++ b/src/Docs/Docs.Logic/CustomMarkdownPage.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ServiceStack.Markdown; + +namespace Docs.Logic +{ + /// + /// Custom base page for all Markdown pages. + /// Provide util methods and setup default variables. + /// + public class CustomMarkdownPage : MarkdownViewBase + { + public override void OnLoad() + { + Page page; + var pageManager = AppHost.TryResolve(); + pageManager.PageMap.TryGetValue(MarkdownPage.FilePath, out page); + + object cat; + this.ScopeArgs.TryGetValue("Category", out cat); + + if (page == null) + page = new Page { Category = cat != null ? cat.ToString() : "Framework" }; + + if (!this.ScopeArgs.ContainsKey("Title")) + this.ScopeArgs.Add("Title", page.Name); + + if (!this.ScopeArgs.ContainsKey("Category")) + this.ScopeArgs.Add("Category", page.Category); + + this.ScopeArgs.Add("PagesMenu", GetPagesMenu(page)); + + var lastModified = MarkdownPage.LastModified.GetValueOrDefault(DateTime.Now); + this.ScopeArgs.Add("ModifiedDay", lastModified.Day); + this.ScopeArgs.Add("ModifiedMonth", lastModified.ToString("MMM")); + } + + public string GetPagesMenu(Page selectedPage) + { + var sb = new StringBuilder(); + sb.Append("
      \n"); + foreach (var kvp in PageManager.Instance.CategoriesMap) + { + var category = kvp.Key; + var categoryPages = kvp.Value; + var categoryUrl = PageManager.Instance.BaseUrl + "category/" + category; + + if (category == selectedPage.Category) + sb.AppendFormat("
    • {1} ({2})\n", categoryUrl, category, categoryPages.Count); + else + sb.AppendFormat("
    • {1} ({2})\n", categoryUrl, category, categoryPages.Count); + + if (category == selectedPage.Category) + { + sb.Append("
        \n"); + foreach (var page in categoryPages) + { + var pageUrl = PageManager.Instance.BaseUrl + page.RelativeUrl; + var cls = selectedPage.FilePath == page.FilePath ? " class='active'" : ""; + sb.AppendFormat("{2}\n", cls, pageUrl, page.Name); + } + sb.Append("
      \n"); + } + + sb.Append("
    • \n"); + } + sb.Append("
    \n"); + return sb.ToString(); + } + + public int Len(IEnumerable items) + { + return items.Count(); + } + } +} diff --git a/src/Docs/Docs.Logic/Docs.Logic.csproj b/src/Docs/Docs.Logic/Docs.Logic.csproj new file mode 100644 index 00000000..50c07eb2 --- /dev/null +++ b/src/Docs/Docs.Logic/Docs.Logic.csproj @@ -0,0 +1,85 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF} + Library + Properties + Docs.Logic + Docs.Logic + v4.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + ..\..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True + + + ..\..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True + + + ..\..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True + + + ..\..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True + + + ..\..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Docs/Docs.Logic/Extensions.cs b/src/Docs/Docs.Logic/Extensions.cs new file mode 100644 index 00000000..3343a665 --- /dev/null +++ b/src/Docs/Docs.Logic/Extensions.cs @@ -0,0 +1,20 @@ +using System.Text.RegularExpressions; +using ServiceStack; + +namespace Docs.Logic +{ + public static class Extensions + { + static readonly Regex AlphanumericRegex = new Regex("[^a-zA-Z-]", RegexOptions.Compiled); + + public static string SafeName(this string name) + { + return AlphanumericRegex.Replace(name.Replace(" ", "-").ToLower(), ""); + } + + public static T DeepClone(this T src) + { + return src.ToJsv().FromJsv(); + } + } +} \ No newline at end of file diff --git a/src/Docs/Docs.Logic/PageManager.cs b/src/Docs/Docs.Logic/PageManager.cs new file mode 100644 index 00000000..56ddca52 --- /dev/null +++ b/src/Docs/Docs.Logic/PageManager.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ServiceStack; + +namespace Docs.Logic +{ + public class PageManager + { + public static PageManager Instance = new PageManager(); + + public List Pages { get; set; } + public Dictionary PageMap { get; set; } + public Dictionary> CategoriesMap { get; set; } + public string BaseUrl; + + public void Init(string filePath, string baseUrl) + { + BaseUrl = baseUrl; + if (File.Exists(filePath)) + { + var json = File.ReadAllText(filePath); + this.Pages = json.FromJson>(); + this.Pages.ForEach(x => x.FilePath = x.FilePath.MapServerPath()); + } + else + { + //First Run: Pages.json doesn't exist let's create and download all remote content + this.Pages = SeedData.Pages; + var basePath = "~".MapServerPath(); + Pages.ForEach(x => x.SaveRemoteContent(basePath, overwrite: false)); + File.WriteAllText(filePath, Pages.ToJson()); + } + + this.PageMap = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + Pages.Where(x => !x.FilePath.IsNullOrEmpty()).Each(x => PageMap[x.FilePath] = x); + + CategoriesMap = new Dictionary>(StringComparer.CurrentCultureIgnoreCase); + foreach (var page in Pages) + { + List pages; + if (!CategoriesMap.TryGetValue(page.Category, out pages)) + { + pages = new List(); + CategoriesMap[page.Category] = pages; + } + + pages.Add(page); + } + } + + } +} \ No newline at end of file diff --git a/src/Docs/Docs.Logic/PageService.cs b/src/Docs/Docs.Logic/PageService.cs new file mode 100644 index 00000000..7734ae52 --- /dev/null +++ b/src/Docs/Docs.Logic/PageService.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ServiceStack; + +namespace Docs.Logic +{ + public class Page + { + public Page() + { + this.Tags = new List(); + } + + public Page(string name, string src, string category, IEnumerable tags) + { + Name = name; + Src = src; + Category = category; + Tags = (tags ?? new List()).ToList(); + } + + public string Name { get; set; } + public string Slug { get; set; } + public string Src { get; set; } + public string FilePath { get; set; } + public string Category { get; set; } + public string Content { get; set; } + public DateTime? CreatedDate { get; set; } + public DateTime? ModifiedDate { get; set; } + public List Tags { get; set; } + + public void SaveRemoteContent(string baseUrl, bool overwrite) + { + try + { + if (!overwrite && this.FilePath != null) + { + var fi = new FileInfo(this.FilePath); + if (fi.Length > 0) + return; + } + + this.Slug = this.Name.SafeName(); + + var remoteContent = GetRemoteContent(); + Save(baseUrl, remoteContent); + } + catch (Exception ex) + { + Console.WriteLine(ex); + throw; + } + } + + public void LoadContent() + { + this.Content = GetContent(); + } + + public string GetContent() + { + return this.FilePath != null + ? File.ReadAllText(this.FilePath) + : GetRemoteContent(); + } + + public string GetRemoteContent() + { + var isGithubWiki = !this.Src.EndsWith(".md"); + if (isGithubWiki) + { + var markdownEditUrl = this.Src + "/_edit"; + var editPageContents = markdownEditUrl.GetStringFromUrl(); + return editPageContents.ExtractContents("", ""); + } + + var markdownUrl = this.Src.Contains("/blob/") + ? this.Src.Replace("/blob/", "/raw/") + : this.Src; + + return markdownUrl.GetStringFromUrl(); + } + + public void Save(string baseUrl, string contents) + { + var cateogryDir = Path.Combine(baseUrl, this.Category.SafeName()); + + if (!Directory.Exists(cateogryDir)) + Directory.CreateDirectory(cateogryDir); + + this.FilePath = Path.Combine(cateogryDir, this.Slug + ".md"); + File.WriteAllText(this.FilePath, contents); + } + + public string RelativeUrl + { + get { return this.Category.SafeName() + "/" + this.Slug; } + } + + public string AbsoluteUrl + { + get { return PageManager.Instance.BaseUrl + this.Category.SafeName() + "/" + this.Slug; } + } + } + + public class PageService : Service + { + public PageManager PageManager { get; set; } + + public object Get(Page request) + { + if (request.Name != null) + { + //Load Content for single pages + var page = PageManager.Pages.FirstOrDefault(x => x.Name == request.Name); + if (page == null) return null; + var clone = page.DeepClone(); + clone.Content = page.GetContent(); + return clone; + } + + return PageManager.Pages; + } + } +} \ No newline at end of file diff --git a/src/Docs/Docs.Logic/Properties/AssemblyInfo.cs b/src/Docs/Docs.Logic/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..ffae65b1 --- /dev/null +++ b/src/Docs/Docs.Logic/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Docs.Logic")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Docs.Logic")] +[assembly: AssemblyCopyright("Copyright © 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("15afbf1d-13b8-42e2-ba05-b2dc18f14f97")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Docs/Docs.Logic/SearchService.cs b/src/Docs/Docs.Logic/SearchService.cs new file mode 100644 index 00000000..9fdd7dea --- /dev/null +++ b/src/Docs/Docs.Logic/SearchService.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using ServiceStack; + +namespace Docs.Logic +{ + public class Search + { + public string Query { get; set; } + } + + public class SearchResponse : IHasResponseStatus + { + public SearchResponse() + { + this.Results = new List(); + } + + public string Query { get; set; } + + public List Results { get; set; } + + public ResponseStatus ResponseStatus { get; set; } + } + + public class SearchService : Service + { + public PageManager PageManager { get; set; } + + public object Get(Search request) + { + var results = new List(); + foreach (var page in PageManager.Pages) + { + var contents = page.GetContent().StripMarkdownMarkup(); + + var pos = 0; + if ((pos = contents.IndexOf(request.Query, StringComparison.CurrentCultureIgnoreCase)) != -1) + { + var resultPage = page.DeepClone(); + var snippet = GetSnippet(contents, pos); + resultPage.Content = snippet.Replace(request.Query, "**" + request.Query + "**"); + results.Add(resultPage); + } + } + return new SearchResponse { + Query = request.Query, + Results = results + }; + } + + private static string GetSnippet(string contents, int pos) + { + var startPos = pos - 50; + var endPos = pos + 100; + if (endPos >= contents.Length) + { + endPos = contents.Length - 1; + startPos = endPos - 100; + } + if (startPos < 0) startPos = 0; + if (contents[startPos] != ' ') + { + var wordBoundaryPos = contents.LastIndexOf(' ', startPos); + if (wordBoundaryPos != -1) startPos = wordBoundaryPos + 1; + } + if (contents[endPos] != ' ') + { + var wordBoundaryPos = contents.IndexOf(' ', endPos); + if (wordBoundaryPos != -1) endPos = wordBoundaryPos; + } + + var snippet = contents.Substring(startPos, endPos - startPos); + + return snippet; + } + } +} \ No newline at end of file diff --git a/src/Docs/Docs.Logic/SeedData.cs b/src/Docs/Docs.Logic/SeedData.cs new file mode 100644 index 00000000..383fb6ff --- /dev/null +++ b/src/Docs/Docs.Logic/SeedData.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace Docs.Logic +{ + public class SeedData + { + public static List Pages = new List + { + new Page("Home", "https://github.com/ServiceStack/ServiceStack/wiki/Home", "ServiceStack", new[]{"GettingStarted"}), + new Page("Overview", "https://github.com/ServiceStack/ServiceStack/blob/master/README.md", "ServiceStack", new[]{"Overview"}), + new Page("Release Notes", "https://github.com/ServiceStack/ServiceStack/wiki/Release-Notes", "ServiceStack", new[]{"ReleaseNotes"}), + new Page("NuGet", "https://github.com/ServiceStack/ServiceStack/wiki/NuGet", "ServiceStack", new[]{"NuGet"}), + new Page("JSON Report Format", "https://github.com/ServiceStack/ServiceStack/wiki/HTML5ReportFormat", "ServiceStack", new[]{"HTML5","Formats","JsonReport"}), + new Page("Caching Options", "https://github.com/ServiceStack/ServiceStack/wiki/Caching", "ServiceStack", new[]{"Caching","Redis","Memcached"}), + new Page("Accessing IHttpRequest", "https://github.com/ServiceStack/ServiceStack/wiki/Access-the-HTTP-Request-in-Web-Services", "ServiceStack", new[]{"API","HTTP"}), + + new Page("ServiceStack Examples", "https://github.com/ServiceStack/ServiceStack.Examples/blob/master/README.md", "Examples", new[]{"GettingStarted", "Overview"}), + + new Page("ServiceStack Contrib", "https://github.com/ServiceStack/ServiceStack.Contrib/blob/master/README.md", "Contrib", new[]{"Contrib", "Overview"}), + + new Page("JSON, CSV, JSV Serializers", "https://github.com/ServiceStack/ServiceStack.Text/blob/master/README.md", "Text Serializers", new[]{"JSON", "JSV", "CSV", "Text", "Overview"}), + new Page("JSV Format", "https://github.com/ServiceStack/ServiceStack.Text/wiki/JSV-Format", "Text Serializers", new[]{"JSV", "Text"}), + + new Page("Redis Client", "https://github.com/ServiceStack/ServiceStack.Redis/blob/master/README.md", "Redis Client", new[]{"Redis"}), + new Page("Redis Overview", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/Home", "Redis Client", new[]{"Redis", "Overview"}), + new Page("Useful Redis Links", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/Useful-Redis-Links", "Redis Client", new[]{"Redis", "Overview"}), + new Page("Redis Release Notes", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/Home", "Redis Client", new[]{"Redis", "Overview", "ReleaseNotes"}), + new Page("Designing NoSQL Database", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/DesigningNoSqlDatabase", "Redis Client", new[]{"Redis", "NoSQL", "Tutorial"}), + new Page("Schemaless NoSQL Migrations", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/MigrationsUsingSchemalessNoSql", "Redis Client", new[]{"Redis", "NoSQL", "Tutorial"}), + new Page("Distributed Locking with Redis", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/MigrationsUsingSchemalessNoSql", "Redis Client", new[]{"Redis", "NoSQL", "Example", "Locks"}), + new Page("Redis Pub/Sub", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/RedisPubSub", "Redis Client", new[]{"Redis", "NoSQL", "Example", "PubSub"}), + new Page("Redis Transactions", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/RedisTransactions", "Redis Client", new[]{"Redis", "NoSQL", "Example", "Transactions"}), + new Page("IRedisClient API", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisClient", "Redis Client", new[]{"Redis", "API", "RedisClient"}), + new Page("IRedisTypedClient API", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisTypedClient", "Redis Client", new[]{"Redis", "API", "RedisClient"}), + new Page("IRedisNativeClient API", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisNativeClient", "Redis Client", new[]{"Redis", "API", "RedisClient"}), + new Page("IRedisTransaction API", "https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisTransaction", "Redis Client", new[]{"Redis", "API", "Transactions"}), + + new Page("Redis Admin UI Overview", "https://github.com/ServiceStack/ServiceStack.RedisWebServices/blob/master/README.md", "Redis Admin UI", new[]{"Redis", "RedisAdminUI", "Overview"}), + + new Page("OrmLite Overview", "https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/README.md", "OrmLite", new[]{"OrmLite", "SqlServer", "Sqlite"}), + + new Page("Logging Overview", "https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/README.md", "Logging", new[]{"Logging", "Log4Net", "EventLog", "Nlog"}), + }; + } +} \ No newline at end of file diff --git a/src/Docs/Docs.Logic/packages.config b/src/Docs/Docs.Logic/packages.config new file mode 100644 index 00000000..6b7d575f --- /dev/null +++ b/src/Docs/Docs.Logic/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Docs/Docs.csproj b/src/Docs/Docs.csproj new file mode 100644 index 00000000..648f32ac --- /dev/null +++ b/src/Docs/Docs.csproj @@ -0,0 +1,208 @@ + + + + + Debug + AnyCPU + + + 2.0 + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Docs + Docs + v4.5 + false + + + + + 4.0 + + + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\ + TRACE + prompt + 4 + false + + + + ..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True + + + ..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True + + + ..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True + + + ..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True + + + ..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + Global.asax + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF} + Docs.Logic + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + False + True + 5416 + / + http://localhost/docs + False + False + + + False + + + + + + + + + + + \ No newline at end of file diff --git a/src/Docs/Docs.gpState b/src/Docs/Docs.gpState new file mode 100644 index 00000000..aa4223b5 --- /dev/null +++ b/src/Docs/Docs.gpState @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/Docs/Docs.sln b/src/Docs/Docs.sln new file mode 100644 index 00000000..22be3218 --- /dev/null +++ b/src/Docs/Docs.sln @@ -0,0 +1,45 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Docs", "Docs.csproj", "{19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Docs.Logic", "Docs.Logic\Docs.Logic.csproj", "{2A606EB5-47BD-47B1-97EB-8C208DF63ABF}" +EndProject +Global + GlobalSection(CodealikeProperties) = postSolution + SolutionGuid = 7cca7660-0007-4068-9d9e-a86e9f73ef00 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Debug|x86.ActiveCfg = Debug|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Any CPU.Build.0 = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {19ADDEEC-EAF9-4B42-8EEC-86CD389D834F}.Release|x86.ActiveCfg = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Debug|x86.ActiveCfg = Debug|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Any CPU.Build.0 = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2A606EB5-47BD-47B1-97EB-8C208DF63ABF}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Docs/Global.asax b/src/Docs/Global.asax new file mode 100644 index 00000000..aba7a8d1 --- /dev/null +++ b/src/Docs/Global.asax @@ -0,0 +1 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="Docs.Global" Language="C#" %> diff --git a/src/Docs/Global.asax.cs b/src/Docs/Global.asax.cs new file mode 100644 index 00000000..2cfa090b --- /dev/null +++ b/src/Docs/Global.asax.cs @@ -0,0 +1,47 @@ +using System; +using System.Linq; +using Docs.Logic; +using Funq; +using ServiceStack; +using ServiceStack.Configuration; +using ServiceStack.Formats; + +namespace Docs +{ + public class AppHost : AppHostBase + { + public AppHost() + : base("ServiceStack Docs", typeof(PageService).Assembly) { } + + public override void Configure(Container container) + { + var baseUrl = ConfigUtils.GetAppSetting("WebHostUrl"); + PageManager.Instance.Init("~/Pages.json".MapServerPath(), baseUrl); + + container.Register(PageManager.Instance); + + Routes + .Add("/pages") + .Add("/pages/{Name}") + .Add("/category/{Name}") + .Add("/search") + .Add("/search/{Query}"); + + SetConfig(new HostConfig { + WebHostUrl = baseUrl, //replaces ~/ with Url + MarkdownBaseType = typeof(CustomMarkdownPage), //set custom base for all Markdown pages + }); + + var plugin = (MarkdownFormat)Plugins.First(x => x is MarkdownFormat); + var page = plugin.FindByPathInfo("/about"); + } + } + + public class Global : System.Web.HttpApplication + { + protected void Application_Start(object sender, EventArgs e) + { + new AppHost().Init(); + } + } +} \ No newline at end of file diff --git a/src/Docs/Pages.json b/src/Docs/Pages.json new file mode 100644 index 00000000..e68c86e5 --- /dev/null +++ b/src/Docs/Pages.json @@ -0,0 +1,274 @@ +[ + { + "Name":"About Docs", + "Slug":"about", + "Src":"https://servicestack.net/docs/markdown/about", + "FilePath":"~/markdown/about.md", + "Category":"Markdown", + "Tags":["Markdown","Docs","About","MarkdownRazor"] + }, + { + "Name":"Markdown Features", + "Slug":"markdown-features", + "Src":"https://servicestack.net/docs/markdown/markdown", + "FilePath":"~/markdown/markdown-features.md", + "Category":"Markdown", + "Tags":["Markdown","MarkdownRazor"] + }, + { + "Name":"Markdown Razor", + "Slug":"markdown-razor", + "Src":"https://servicestack.net/docs/markdown/markdown-razor", + "FilePath":"~/markdown/markdown-razor.md", + "Category":"Markdown", + "Tags":["Markdown","Docs","About","MarkdownRazor"] + }, + { + "Name":"Home", + "Slug":"home", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/Home", + "FilePath":"~/framework/home.md", + "Category":"Framework", + "Tags":["GettingStarted"] + }, + { + "Name":"Overview", + "Slug":"overview", + "Src":"https://github.com/ServiceStack/ServiceStack/blob/master/README.md", + "FilePath":"~/framework/overview.md", + "Category":"Framework", + "Tags":["Overview"] + }, + { + "Name":"Release Notes", + "Slug":"release-notes", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/Release-Notes", + "FilePath":"~/framework/release-notes.md", + "Category":"Framework", + "Tags":["ReleaseNotes"] + }, + { + "Name":"NuGet", + "Slug":"nuget", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/NuGet", + "FilePath":"~/framework/nuget.md", + "Category":"Framework", + "Tags":["NuGet"] + }, + { + "Name":"JSON Report Format", + "Slug":"json-report-format", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/HTML5ReportFormat", + "FilePath":"~/framework/json-report-format.md", + "Category":"Framework", + "Tags":["HTML5","Formats","JsonReport"] + }, + { + "Name":"Caching Options", + "Slug":"caching-options", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/Caching", + "FilePath":"~/framework/caching-options.md", + "Category":"Framework", + "Tags":["Caching","Redis","Memcached"] + }, + { + "Name":"Accessing IHttpRequest", + "Slug":"accessing-ihttprequest", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/Access-the-HTTP-Request-in-Web-Services", + "FilePath":"~/framework/accessing-ihttprequest.md", + "Category":"Framework", + "Tags":["API","HTTP"] + }, + { + "Name":"History of Web Services", + "Slug":"history-of-webservices", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/Service-Stack-Web-Services", + "FilePath":"~/framework/history-of-webservices.md", + "Category":"Framework", + "Tags":["HTTP","WebServices","JSON","POX","SOAP"] + }, + { + "Name":"CSV Format", + "Slug":"csv-format", + "Src":"https://github.com/ServiceStack/ServiceStack/wiki/ServiceStack-CSV-Format", + "FilePath":"~/framework/csv-format.md", + "Category":"Framework", + "Tags":["CSV","CustomFormat"] + }, + { + "Name":"Redis Client", + "Slug":"redis-client", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/blob/master/README.md", + "FilePath":"~/redis-client/redis-client.md", + "Category":"Redis Client", + "Tags":["Redis"] + }, + { + "Name":"Redis Overview", + "Slug":"redis-overview", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/Home", + "FilePath":"~/redis-client/redis-overview.md", + "Category":"Redis Client", + "Tags":["Redis","Overview"] + }, + { + "Name":"Useful Redis Links", + "Slug":"useful-redis-links", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/Useful-Redis-Links", + "FilePath":"~/redis-client/useful-redis-links.md", + "Category":"Redis Client", + "Tags":["Redis","Overview"] + }, + { + "Name":"Redis Release Notes", + "Slug":"redis-release-notes", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/Home", + "FilePath":"~/redis-client/redis-release-notes.md", + "Category":"Redis Client", + "Tags":["Redis","Overview","ReleaseNotes"] + }, + { + "Name":"Designing NoSQL DB's", + "Slug":"designing-nosql-database", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/DesigningNoSqlDatabase", + "FilePath":"~/redis-client/designing-nosql-database.md", + "Category":"Redis Client", + "Tags":["Redis","NoSQL","Tutorial"] + }, + { + "Name":"Schemaless Migrations", + "Slug":"schemaless-nosql-migrations", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/MigrationsUsingSchemalessNoSql", + "FilePath":"~/redis-client/schemaless-nosql-migrations.md", + "Category":"Redis Client", + "Tags":["Redis","NoSQL","Tutorial"] + }, + { + "Name":"Distributed Locking", + "Slug":"distributed-locking-with-redis", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/MigrationsUsingSchemalessNoSql", + "FilePath":"~/redis-client/distributed-locking-with-redis.md", + "Category":"Redis Client", + "Tags":["Redis","NoSQL","Example","Locks"] + }, + { + "Name":"Redis Pub/Sub", + "Slug":"redis-pubsub", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/RedisPubSub", + "FilePath":"~/redis-client/redis-pubsub.md", + "Category":"Redis Client", + "Tags":["Redis","NoSQL","Example","PubSub"] + }, + { + "Name":"Redis Transactions", + "Slug":"redis-transactions", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/RedisTransactions", + "FilePath":"~/redis-client/redis-transactions.md", + "Category":"Redis Client", + "Tags":["Redis","NoSQL","Example","Transactions"] + }, + { + "Name":"IRedisClient API", + "Slug":"iredisclient-api", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisClient", + "FilePath":"~/redis-client/iredisclient-api.md", + "Category":"Redis Client", + "Tags":["Redis","API","RedisClient"] + }, + { + "Name":"IRedisTypedClient API", + "Slug":"iredistypedclient-api", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisTypedClient", + "FilePath":"~/redis-client/iredistypedclient-api.md", + "Category":"Redis Client", + "Tags":["Redis","API","RedisClient"] + }, + { + "Name":"IRedisNativeClient API", + "Slug":"iredisnativeclient-api", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisNativeClient", + "FilePath":"~/redis-client/iredisnativeclient-api.md", + "Category":"Redis Client", + "Tags":["Redis","API","RedisClient"] + }, + { + "Name":"IRedisTransaction API", + "Slug":"iredistransaction-api", + "Src":"https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisTransaction", + "FilePath":"~/redis-client/iredistransaction-api.md", + "Category":"Redis Client", + "Tags":["Redis","API","Transactions"] + }, + { + "Name":"Redis Admin UI Overview", + "Slug":"redis-admin-ui-overview", + "Src":"https://github.com/ServiceStack/ServiceStack.RedisWebServices/blob/master/README.md", + "FilePath":"~/redis-admin-ui/redis-admin-ui-overview.md", + "Category":"Redis Admin UI", + "Tags":["Redis","RedisAdminUI","Overview"] + }, + { + "Name":"JSON, CSV, JSV Text Serializers", + "Slug":"json-csv-jsv-serializers", + "Src":"https://github.com/ServiceStack/ServiceStack.Text/blob/master/README.md", + "FilePath":"~/text-serializers/json-csv-jsv-serializers.md", + "Category":"Text Serializers", + "Tags":["JSON","JSV","CSV","Text","Overview"] + }, + { + "Name":"JSON Serializer", + "Slug":"json-serializer", + "Src":"", + "FilePath":"~/text-serializers/json-serializer.md", + "Category":"Text Serializers", + "Tags":["JSON","Text","Overview"] + }, + { + "Name":"JSV Format", + "Slug":"jsv-format", + "Src":"https://github.com/ServiceStack/ServiceStack.Text/wiki/JSV-Format", + "FilePath":"~/text-serializers/jsv-format.md", + "Category":"Text Serializers", + "Tags":["JSV","Text"] + }, + { + "Name":"Override MVCs JsonResult", + "Slug":"override-mvc-jsonresult", + "Src":"https://github.com/ServiceStack/ServiceStack.Text/wiki/Override-MVCs-JsonResult", + "FilePath":"~/text-serializers/override-mvc-jsonresult.md", + "Category":"Text Serializers", + "Tags":["JSON","Text","JsonResult","MVC"] + }, + { + "Name":"ServiceStack Examples", + "Slug":"servicestack-examples", + "Src":"https://github.com/ServiceStack/ServiceStack.Examples/blob/master/README.md", + "FilePath":"~/examples/servicestack-examples.md", + "Category":"Examples", + "Tags":["GettingStarted","Overview"] + }, + { + "Name":"OrmLite Overview", + "Slug":"ormlite-overview", + "Src":"https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/README.md", + "FilePath":"~/ormlite/ormlite-overview.md", + "Category":"OrmLite", + "Tags":["OrmLite","SqlServer","Sqlite"] + }, + { + "Name":"ServiceStack Contrib", + "Slug":"servicestack-contrib", + "Src":"https://github.com/ServiceStack/ServiceStack.Contrib/blob/master/README.md", + "FilePath":"~/contrib/servicestack-contrib.md", + "Category":"Contrib", + "Tags":["Contrib","Overview"] + }, + { + "Name":"Logging Overview", + "Slug":"logging-overview", + "Src":"https://github.com/ServiceStack/ServiceStack.Logging/blob/master/README.md", + "FilePath":"~/logging/logging-overview.md", + "Category":"Logging", + "Tags":["Logging","Log4Net","EventLog","Nlog"] + } +] \ No newline at end of file diff --git a/src/StarterTemplates/RootPath35/Properties/AssemblyInfo.cs b/src/Docs/Properties/AssemblyInfo.cs similarity index 88% rename from src/StarterTemplates/RootPath35/Properties/AssemblyInfo.cs rename to src/Docs/Properties/AssemblyInfo.cs index 65678382..4b35335d 100644 --- a/src/StarterTemplates/RootPath35/Properties/AssemblyInfo.cs +++ b/src/Docs/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("RootPath35")] +[assembly: AssemblyTitle("ServiceStack.Docs")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("RootPath35")] +[assembly: AssemblyProduct("ServiceStack.Docs")] [assembly: AssemblyCopyright("Copyright © 2011")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("d48243b6-2718-4757-b5cf-a9d91bf27ab8")] +[assembly: Guid("45985818-7f84-4d07-9d7a-16c3ab7376cb")] // Version information for an assembly consists of the following four values: // diff --git a/src/Docs/Views/Category.md b/src/Docs/Views/Category.md new file mode 100644 index 00000000..6a942649 --- /dev/null +++ b/src/Docs/Views/Category.md @@ -0,0 +1,8 @@ +@var Category = Model.Name +@var Title = Category + +#### Category Pages + +@foreach page in Model.Results { + - [@page.Name](@page.AbsoluteUrl) +} diff --git a/src/Docs/Views/Search.md b/src/Docs/Views/Search.md new file mode 100644 index 00000000..09377b33 --- /dev/null +++ b/src/Docs/Views/Search.md @@ -0,0 +1,26 @@ +@var Title = "Search results for " + Model.Query + +@if (Model.Results.Count == 0) { + +#### Your search did not match any documents. + +## Suggestions: + + - Make sure all words are spelled correctly. + - Try different keywords. + - Try more general keywords. + - Try fewer keywords. +} else { + +#### Showing Results 1 - @Model.Results.Count + +^
    + +@foreach page in Model.Results { +### @page.Category > [@page.Name](@page.AbsoluteUrl) +@page.Content +} + +^
    + +} \ No newline at end of file diff --git a/src/Docs/Views/Shared/_Layout.shtml b/src/Docs/Views/Shared/_Layout.shtml new file mode 100644 index 00000000..eacde62f --- /dev/null +++ b/src/Docs/Views/Shared/_Layout.shtml @@ -0,0 +1,156 @@ + + + + + <!--@Title--> + + + + + + + + + +
    + + + + +
    + + RSS +
    +
    +
    +  
    + +
    +
    +

    + +

    +
    +
    + + +
    +
    +
    +
    + +
    + +
    + +
     
    +
    +
    +
    + Comments Off +

    + Posted + + in

    +
    +
    +  
    +
    +
    + +
    + + + + +
    +  
    +
    +
    +
    + + + + +
    + + + + + + + + + diff --git a/src/Docs/Web.config b/src/Docs/Web.config new file mode 100644 index 00000000..9f184825 --- /dev/null +++ b/src/Docs/Web.config @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Docs/contrib/servicestack-contrib.md b/src/Docs/contrib/servicestack-contrib.md new file mode 100644 index 00000000..453a1f1e --- /dev/null +++ b/src/Docs/contrib/servicestack-contrib.md @@ -0,0 +1,27 @@ +# Useful high-level App and use-case specific features and utils + + +##ServiceStack.ServiceInterface.dll + +Generic, Common and High-level functionality to assist with your web services implementation. + +The ServiceBase and RestServiceBase classes provide use-ful base classes for your web services to inherit from. + +#### ServiceBase - base class for RPC services + + * Handles C# exceptions and serializes them into your Response DTO's so your clients can programatically access them + * If you have a IRedisClient installed, rolling error logs will be maintained so you can easily see the latest errors + * **base.ResolveService()** - let's you access a pre-configured instance of another web service so you can delegate required functionality + * **base.AppHost** - Accesses the underlying AppHost letting you inspect its configuration, etc + +#### RestServiceBase - base class for REST Services (extends ServiceBase) + + * Reduces the boiler-plate by already implementing all REST operations so you don't have to e.g. IRestGetService + + +#### ServiceModel +Generic DTO types useful for all web services. e.g. **ResponseStatus** is where C# exceptions get injected into + +#### Session +Existing classes to help manage a users session + diff --git a/src/Docs/css/default.css b/src/Docs/css/default.css new file mode 100644 index 00000000..5d5669f9 --- /dev/null +++ b/src/Docs/css/default.css @@ -0,0 +1,191 @@ +/* +Theme name: ChocoTheme +Theme URI: http://cssmayo.com/freebies/free-wordpress-themes/chocotheme/ +Description: Stylish WordPress theme with two columns, right-sidebar. 3 color schemes availible. Theme options panel for background and navigation configuration. +Author: CSSMayo +Author URI: http://cssmayo.com/ +Version: 0.10 +Tags: theme-options, custom-colors, two-columns, dark, brown +*/ + +* { padding: 0; margin: 0; outline: 0; } + +body { + font-size: 13px; + line-height: 1.4; + font-family: Arial, "Trebuchet MS", Sans-Serif; + color: #444; + background: #3a2820; + text-align: left; +} + +a img { border: 0; } +a { color: #cd4517; text-decoration: none; cursor: pointer; } +a:hover { text-decoration: underline; } + +h2, h3, h4, h5, h6 { font-family: "Trebuchet MS", "Myriad Pro", Tahoma, Sans-Serif; font-weight: normal; line-height: 1.2; } + +input, textarea, select, button, label { font-family: Arial, "Trebuchet MS", Sans-Serif; font-size: 12px; color: #444; } +div.field { width: 280px; height: 15px; background: url(../img/field.gif) no-repeat 0 0; padding: 8px 5px 7px; overflow: hidden; } +div.textarea { width: 324px; height: 125px; padding: 8px 5px 7px; background: url(../img/textarea.gif) no-repeat 0 0; } +div.field input, +div.textarea textarea { border: none; background: none; width: 100%; } +div.textarea textarea { height: 125px; } + +.cl, .clear { display: block; height: 0; font-size: 0; line-height: 0; text-indent: -4000px; clear: both; } + +.alignright { float: right; } +.alignleft { float: left; } + +p img { padding: 0; max-width: 100%; } +img.centered { display: block; margin-left: auto; margin-right: auto; } +img.alignright { margin: 0 0 5px 15px; display: inline; } +img.alignleft { margin: 0 15px 5px 0; display: inline; } + +#page { width: 980px; margin: 0 auto; } + +#header { padding-top: 30px; height: 85px; position: relative; z-index: 100; } +#header .description { font-size: 13px; line-height: 1; text-transform: uppercase; color: #c1ab7d; padding-top: 5px; } +#header .description a { color: #9d6510; text-decoration: none; } + +h1 { font-family: "Trebuchet MS", Arial, Sans-Serif; font-size: 36px; line-height: 1; font-weight: bold; color: #d69959; } +h1 a { text-decoration: none; color: #d69959; } +h1 a span { color: #ffd7a5; } +h1 a:hover { text-decoration: none; } + +#logo { float: left; display: inline; } + +#nav { float: right; display: inline; font-weight: bold; font-size: 12px; line-height: 30px; text-transform: uppercase; margin-top: 20px; } +#nav ul li { float: left; display: inline; list-style-type: none; position: relative; } +#nav ul li a { color: #fefefe; text-decoration: none; float: left; display: inline; padding-left: 18px; margin-right: 18px; margin-left: 5px; z-index: 10; position: relative; } +#nav ul li a span { float: left; display: inline; padding-right: 18px; margin-right: -18px; position: relative; background-position: right 0 !important; } +#nav ul li a span span { padding-right: 18px; margin-right: -10px; background: url(../img/nav-dd-arr.gif) no-repeat right center !important; padding-bottom: 0; } +#nav ul li.hover a, +#nav ul li.hover a span { background-image: url(../img/has_dropdown-hover.png) !important; color: #000; } +#nav ul li.hover a span span { background-image: url(../img/nav-dd-arr.gif) !important; } +#nav ul li .dropdown { display: none; background: #fff; border: solid 1px #2d2d2d; position: absolute; top: 29px; left: 5px; z-index: 1; width: 176px; padding: 20px 3px 0; } +#nav ul li .dropdown { text-transform: none; font-weight: normal; line-height: 22px; } +#nav ul li .dropdown ul li { border-bottom: dashed 1px #d3d5d5; float: none; display: block; } +#nav ul li .dropdown ul li a { color: #9b9b9b; padding: 0; margin: 0; background: url(../img/arr-2.gif) no-repeat 7px center !important; float: none; display: block; } +#nav ul li .dropdown ul li a:hover { color: #000; background: url(../img/arr-2.gif) no-repeat 7px center !important; } +#nav ul li .dropdown ul li a { padding-left: 15px; } +#nav ul li .dropdown .dropdown { display: none; left: 176px; top: 0; padding-top: 0; } +#nav ul li.last { border-bottom: 0 !important; } + +#footer { padding: 15px 0 30px; text-align: center; font-size: 11px; color: #7e6a4f; } +#footer a { color: #9d6510; text-decoration: none; } +#footer a:hover { text-decoration: underline; } +#footer p.rss { display: inline; padding-left: 14px; background: url(../img/ico-rss-2.png) no-repeat 0 center; } +#footer p.rss a { color: #7e6a4f; } + +#main { background: repeat-y 0 0; width: 100%; position: relative; } +#main-top { background: no-repeat 0 0; } +#main-bot { background: no-repeat 0 bottom; height: 100%; padding: 50px 20px 70px 60px; min-height: 150px; } + +#rss-link { display: block; width: 50px; height: 55px; font-size: 0; line-height: 0; text-indent: -4000px; } +#rss-link { position: absolute; top: -12px; right: -12px; } + +#content { float: left; display: inline; width: 645px; } + +.post { padding-bottom: 30px; background: url(../img/post-bg.gif) no-repeat 0 bottom; margin-bottom: 10px; position: relative; height: 100%; } +.post h2, .list-page .post h3 { font-size: 27px; margin-bottom: 22px; } +.post h2 a, .list-page .post h3 a { color: #000; text-decoration: none; } +.post h2 a:hover, .list-page .post h3 a:hover { text-decoration: none; } +.post .date { position: absolute; top: -7px; left: -123px; width: 75px; height: 80px; text-align: center; } +.post .date .bg { background: no-repeat 0 0; width: 70px; height: 62px; padding: 18px 0 0 5px; } +.post .date span { display: block; font-size: 16px; font-weight: bold; color: #f4b995; line-height: 1; text-transform: uppercase; } +.post .date span.day { font-size: 26px; } +.post .entry img { background: #fff; padding: 2px; border: solid 10px #e2e2e2; } +.post .entry img.wp-smiley { background: #fff; padding: 0px; border: 0; } +.post .entry p { margin-bottom: 18px; } +.post .meta { padding-top: 13px; background: url(../img/meta-top.gif) no-repeat 0 0; } +.post .meta { font-size: 10px; font-family: Verdana, Tahoma, Arial, Sans-Serif; color: #444; } +.post .meta p { padding: 5px 0; line-height: 15px; } +.post .meta .bg { background: #fafafa url(../img/meta-bg.gif) repeat-x 0 bottom; border-left: solid 1px #dedede; border-right: solid 1px #dedede; padding: 0 10px; height: 100%} +.post .meta .bot { height: 4px; font-size: 0; line-height: 0; text-indent: -4000px; background: url(../img/meta-bot.gif) no-repeat 0 0; } +.post .meta .comments-num { float: right; display: inline; font-size: 11px; color: #682815; font-weight: bold; } +.post .meta .comments-num { padding: 5px 0 5px 30px; margin-left: 10px; background: url(../img/meta-comments-num.gif) no-repeat 0 3px; } + +.list-page #searchform { margin-top: 20px; } + +#sidebar { float: right; display: inline; width: 204px; margin-top: 80px; } +.widget_calendar { width: 204px } +#sidebar a { color: #FFE6A8; } + +#sidebar h2 { line-height: 52px; width: 185px; background: no-repeat 0 0; color: #2e2019; font-size: 20px; padding-left: 15px; } +#sidebar ul li { list-style-type: none; } +#sidebar ul li select { margin: 10px 0 10px 10px; width: 183px; padding: 2px; } +#sidebar ul ul { padding: 0 10px 10px 3px; } +#sidebar ul ul li { background: no-repeat 0 4px; border-bottom: solid 1px #423028; margin: 4px 6px; padding-left: 15px} +#sidebar ul ul li ul { border: 0; padding-bottom: 0; } +#sidebar ul ul li li { border: 0; padding-bottom: 5px; margin-bottom: 0; } + +#sidebar ul div { padding: 0 10px 10px 9px } + +#calendar_wrap { width: 203px; font-size: 12px; text-align: center; color: #f7f7f7; padding: 0 0 10px !important; } +#calendar_wrap .nav { font-weight: bold; color: #c4a158; line-height: 24px; width: 130px; margin: 0 auto; position: relative; } + +#wp-calendar { width: 100%; } +#wp-calendar tbody tr td a { border: dashed 1px #c4a158; color: #c4a158; text-decoration: none; width: 16px; line-height: 16px; text-align: center; margin: 0 auto; display: block; } +#wp-calendar tbody tr td { border-right: solid 1px #423028; padding: 2px 0; } +#wp-calendar tbody tr th { border: solid 1px #423028; border-left: 0; padding: 2px 0; color: #b5573a; font-weight: normal; } +#wp-calendar tbody tr .last { border-right: none !important; } +#wp-calendar tbody tr.last td { border-bottom: solid 1px #423028; } + +#sidebar #searchform { margin: 5px 0 15px 5px; } +#sidebar #searchform label { font-weight: bold; color: #c4a158; display: none; } +#sidebar #searchform .field-place { width: 190px; height: 23px; background: no-repeat 0 0; padding: 2px; } +#sidebar #searchform .field-place .field { border: 0; color: #c4a158; padding: 4px 5px 3px; width: 155px; background: none; float: left; display: inline; } +#sidebar #searchform .field-place .button { float: right; display: inline; width: 23px; height: 23px; } +#sidebar #searchform .field-place .button { font-size: 0; line-height: 0; text-indent: -4000px; background: none; border: 0; cursor: pointer; } + +#respond { padding-bottom: 30px; background: url(../img/post-bg.gif) no-repeat 0 bottom; margin-bottom: 10px; } +#respond h3 { font-size: 19px; } +#respond div.left { float: left; display: inline; width: 290px; } +#respond div.right { float: right; display: inline; width: 334px; } +#respond label { display: block; color: #ac2e13; font-size: 12px; margin: 5px 0 3px; } +#respond .button { float: right; display: inline; margin-top: 20px; width: 119px; height: 30px; background: no-repeat 0 0; } +#respond .button { border: 0; cursor: pointer; color: #fff; font-weight: bold; } + +.comment { list-style-type: none; font-size: 12px; } +.comment .comment-body { position: relative; height: 100%; position: relative; padding-left: 80px; padding-bottom: 25px; background: url(../img/post-bg.gif) no-repeat 0 bottom; margin-bottom: 15px; min-height: 90px; } +.comment .avatar { position: absolute; top: 0; left: 0; } +.comment .author { font-weight: bold; line-height: 1; } +.comment .author a { color: #dd5324; } +.comment .comment-meta { font-size: 10px; color: #b49969; margin-bottom: 3px; } +.comment .comment-content p { margin-bottom: 15px; } +.trackback .comment-body, .pingback .comment-body { padding-left: 0; } +/* Big images in rich text editor should not break page layout */ +.post .entry { overflow: hidden; } +/* Default size for headers */ +.post .entry h1 { font-size: 20px; line-height: 30px} +.post .entry h2 { font-size: 18px; line-height: 27px} +.post .entry h3 { font-size: 16px; line-height: 24px} +.post .entry h4 { font-size: 14px; line-height: 21px} +.post .entry h5 { font-size: 12px; line-height: 18px} +.post .entry h6 { font-size: 10px; line-height: 15px} + +/* Reasanble margins for lists */ +.post .entry ul { margin-left: 25px; } +.post .entry ol { margin-left: 25px; } + +.widget { color: #fff } +.userloggedbtn {float: left !important; margin-left: 218px} +.commentsnavigation { margin: 6px auto; } +.reply { float: right; } +.archives hr { margin: 6px 0; } +.wp-caption { border: solid 1px #eee; text-align: center; margin: 6px} +.wp-caption p { margin-bottom: 0 !important; padding: 0 5px;} +.post .entry .wp-caption a img { border: 0 } +.metaplace { padding: 9px; } +.metaplace p {color: #fff } +.commentlist li.last .comment-body { background-image: none; } +.commentlist ul.children { margin-left: 25px; } + +p.tags { padding: 10px; font-size: 10px} +.aligncenter { display: block; margin-left: auto; margin-right: auto; } +.alignleft { float: left; } +.alignright { float: right; } + +h2.pagetitle { font-size: 20px; } + \ No newline at end of file diff --git a/src/Docs/css/styles.css b/src/Docs/css/styles.css new file mode 100644 index 00000000..9ae904a6 --- /dev/null +++ b/src/Docs/css/styles.css @@ -0,0 +1,49 @@ +body { background: #000; } + +#logo a { color: #fff; } +#header .description { color: #848282; } + +.post .date .bg { background-image: url(../img/date.png); } +.post .date span { color: #feefcc; } + +#main { background-image: url(../img/main-bg.jpg); } +#main-top { background-image: url(../img/main-top.jpg); } +#main-bot { background-image: url(../img/main-bot.jpg); } + +#rss-link { background-image: url(../img/ico-rss.png); } + +#sidebar h2 { background-image: url(../img/widgettitle.jpg); color: #fff; } +#sidebar ul ul li { background-image: url(../img/sidebar-list-arr.gif); border-bottom-color: #363636; } + +#sidebar #searchform label { color: #ebab00; } +#sidebar #searchform .field-place { background-image: url(../img/searchform-field.gif); } +#sidebar #searchform .field-place .field { color: #ffe6a8; } + +#respond .button { background-image: url(../img/button.gif); } + +#nav ul li.current_page_item a, +#nav ul li.current_page_item a span { background-image: url(../img/nav-active.png); } + +/* Custom Styles */ +html, body { height: 100%; margin: 0 0 1px; padding: 0; } html {overflow-y:scroll; }/* force scrollbars */ +.hidden { display: none; } +pre{margin:1em 0;font-size:12px;background-color:#eee;border:1px solid #ddd;padding:5px;line-height:1.5em;color:#444;overflow:auto;-webkit-box-shadow:rgba(0,0,0,0.07) 0 1px 2px inset;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} +pre::-webkit-scrollbar{height:8px;width:8px;} +pre::-webkit-scrollbar-track-piece{margin-bottom:10px;background-color:#e5e5e5;border-bottom-left-radius:4px 4px;border-bottom-right-radius:4px 4px;border-top-left-radius:4px 4px;border-top-right-radius:4px 4px;} +pre::-webkit-scrollbar-thumb:vertical{height:25px;background-color:#ccc;-webkit-border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(255,255,255,1);} +pre::-webkit-scrollbar-thumb:horizontal{width:25px;background-color:#ccc;-webkit-border-radius:4px;} +pre code{padding:0!important;font-size:12px!important;background-color:#eee!important;border:none!important;} +code{font-size:12px!important;background-color:#f8f8ff!important;color:#444!important;padding:0 .2em!important;border:1px solid #dedede!important;} +h3, .post .entry h3 { font-size: 18px; } +blockquote{margin:1em 0!important;border-left:5px solid #ddd!important;padding-left:.6em!important;color:#555!important;} +ul { margin-bottom: 10px; } +.post .entry li > p { margin-bottom: 0; } +.post .entry ol + p { margin-top: 10px; } +.post .entry img { background: #fff; padding: 1px; border: solid 1px #E2E2E2; } +.post h2 { margin-bottom: 5px; } +#sidebar ul ul { padding: 0 0 10px 3px; } + +#searchresults { border-top: 1px dotted #D2D2D2; border-bottom: 1px dotted #D2D2D2; padding: 10px 0; } +LI.active > a { color: #f1f1f1 !important; } + +#about-section { float: right;margin: 30px;} \ No newline at end of file diff --git a/src/Docs/default.htm b/src/Docs/default.htm new file mode 100644 index 00000000..5b77d46d --- /dev/null +++ b/src/Docs/default.htm @@ -0,0 +1,282 @@ + + + + + ServiceStack Docs + + + + + + + +
    + + + + +
    + + RSS +
    +
    +
    +  
    + +
    +
    +

    Welcome to ServiceStack Docs

    +
    +
    + 04 + Jun +
    +
    +
    +

    + ServiceStack docs is a collection of all documentation found in the README.md and wiki pages that are in amongst all of ServiceStack's GitHub Open Source projects. +

    +
    +

    About this web site

    + +
    +

    REST and RPC Web Services Framework

    + +

    C# Redis Client

    + +

    Redis Admin UI and Redis Web Services

    + +

    ServiceStack.Text JSON, CSV and JSV Serializers

    + +

    ServiceStack Example projects and Starter Templates

    + +

    OrmLite - Fast, Lite Orm for Sqlite and SqlServer

    + +

    Contrib - Complementary libraries and Utils for developing web services

    + +

    ServiceStack.Logging - Dependency-free logging interface

    + +
    +  
    +
    +
    +
    + + Comments Off +

    + Posted + + in Framework +

    +
    +
    +  
    +
    +
    + +
    + + + + +
    +  
    +
    +
    +
    + + + + +
    + + + + + \ No newline at end of file diff --git a/src/Docs/examples/servicestack-examples.md b/src/Docs/examples/servicestack-examples.md new file mode 100644 index 00000000..403f8aa6 --- /dev/null +++ b/src/Docs/examples/servicestack-examples.md @@ -0,0 +1,46 @@ +[Join the new google group](http://groups.google.com/group/servicestack) or +follow [@demisbellot](http://twitter.com/demisbellot) and [@ServiceStack](http://twitter.com/servicestack) +for twitter updates. + +#Example Projects built with [ServiceStack](~/framework/overview), [C# RedisClient](~/redis-client/redis-client), [OrmLite](~/ormlite/ormlite-overview), etc + +## Live Demo + +A live demo and tutorials are available at the following locations: + +### [Backbone.js TODO app with REST and Redis backend](http://mono.servicestack.net/Backbone.Todos/) +[![Backbone REST and Redis TODOs](http://mono.servicestack.net/showcase/img/todos-400x350.png)](http://mono.servicestack.net/Backbone.Todos/) + +### [Creating a Hello World Web service from scratch](http://mono.servicestack.net/ServiceStack.Hello/) +[![ServiceStacks Hello, World!](http://mono.servicestack.net/showcase/img/hello-400x350.png)](http://mono.servicestack.net/ServiceStack.Hello/) + +### [GitHub-like browser to manage remote filesystem over REST](http://mono.servicestack.net/RestFiles/) +[![GitHub-like REST Files](http://mono.servicestack.net/showcase/img/restfiles-400x350.png)](http://mono.servicestack.net/RestFiles/) + +### [Creating a StackOverflow-like app in Redis](http://mono.servicestack.net/RedisStackOverflow/) +[![Redis StackOverflow](http://mono.servicestack.net/showcase/img/redisstackoverflow-400x350.png)](http://mono.servicestack.net/RedisStackOverflow/) + +### [Complete REST Web service example](http://mono.servicestack.net/ServiceStack.MovieRest/) +[![REST at the Movies!](http://mono.servicestack.net/showcase/img/movierest-400x350.png)](http://mono.servicestack.net/ServiceStack.MovieRest/) + +### [Calling Web Services with Ajax](http://mono.servicestack.net/ServiceStack.Examples.Clients/) +[![Ajax Example](http://mono.servicestack.net/showcase/img/ajaxexample-400x350.png)](http://mono.servicestack.net/ServiceStack.Examples.Clients/) + +### Other examples +* [Calling Web Services with Mono Touch](http://www.servicestack.net/monotouch/remote-info/) +* [Calling Web Services using Silverlight](http://mono.servicestack.net/ServiceStack.Examples.Clients/Silverlight.htm) +* [Calling SOAP 1.1 Web Service Examples](http://mono.servicestack.net/ServiceStack.Examples.Clients/Soap11.aspx) +* [Calling SOAP 1.2 Web Service Examples](http://mono.servicestack.net/ServiceStack.Examples.Clients/Soap12.aspx) + +_All live examples hosted on CentOS/Nginx/FastCGI/Mono_ + +# Download + +You can find the latest releases for download at: + +* [ServiceStack.Examples/downloads](https://github.com/ServiceStack/ServiceStack.Examples/downloads) + + +### Troubleshooting + +- Since the example project uses 32bit Sqlite.dll, on a 64bit machine you must set IIS to run 32bit apps (in the App Domain config) \ No newline at end of file diff --git a/src/Docs/favicon.ico b/src/Docs/favicon.ico new file mode 100644 index 00000000..af0117ed Binary files /dev/null and b/src/Docs/favicon.ico differ diff --git a/src/Docs/framework/accessing-ihttprequest.md b/src/Docs/framework/accessing-ihttprequest.md new file mode 100644 index 00000000..c216c4dc --- /dev/null +++ b/src/Docs/framework/accessing-ihttprequest.md @@ -0,0 +1,69 @@ +# Access the HTTP Request in Web Services + +By default ServiceStack provides a clean, dependency-free IService to implement your Web Services logic in. The philosophy behind this approach is that the less dependencies you have on your environment and its request context, the more testable and re-usable your services become. + +### Advantages for living without it +If you don't need to access the HTTP Request context there is nothing stopping you from having your same IService implementation processing requests from a message queue which we've done for internal projects (which incidentally is the motivation behind the **asynconeway** endpoint, to signal requests that are safe for deferred execution). + +## Injecting the IRequestContext into your Service +Although working in a clean-room can be ideal ideal from re-usability and testability point of view, you stand the chance of missing out a lot of the features present in HTTP. So not wanting to limit your web services usefulness, this feature of accessing the RequestContext has been present in ServiceStack from early on however because it hasn't been well documented its not very well-known (An issue this wiki page hopes to correct :) + +Just like using built-in Funq IOC container, the way to tell ServiceStack to inject the request context is by implementing the [IRequiresRequestContext](https://github.com/ServiceStack/ServiceStack.Interfaces/blob/master/src/ServiceStack.ServiceHost/IRequiresRequestContext.cs) interface which will get the [IRequestContext](https://github.com/ServiceStack/ServiceStack.Interfaces/blob/master/src/ServiceStack.ServiceHost/IRequestContext.cs) inject before each request. + + public interface IRequestContext : IDisposable + { + T Get() where T : class; + + string IpAddress { get; } + + IDictionary Cookies { get; } + + EndpointAttributes EndpointAttributes { get; } + + IRequestAttributes RequestAttributes { get; } + + string MimeType { get; } + + string CompressionType { get; } + + string AbsoluteUri { get; } + + IFile[] Files { get; } + } + + +This will allow your services to inspect any Cookies or download any Files that were sent with the request. +Note: to set Response Cookies or Headers, return the [HttpResult](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/Web/HttpResult.cs) object. + +## Accessing the IHttpRequest and IHttpResponse using filters +A recent addition to ServiceStack is the ability to register custom Request and Response filters. These should be registered in your AppHost.Configure() onload script: + +* The Request Filters are applied before the service gets called and accepts: +_([IHttpRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceHost/IHttpRequest.cs), [IHttpResponse](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceHost/IHttpResponse.cs), RequestDto)_ e.g: + + //Add a request filter to check if the user has a session initialized + this.RequestFilters.Add((httpReq, httpReq, requestDto) => + { + var sessionId = httpReq.GetCookieValue("user-session"); + if (sessionId == null) + { + httpReq.ReturnAuthRequired(); + } + }); + + +* The Response Filters are applied after your service is called and accepts: +_([IHttpRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceHost/IHttpRequest.cs), [IHttpResponse](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceHost/IHttpResponse.cs), ResponseDto)_ e.g: + + //Add a response filter to add a 'Content-Disposition' header so browsers treat it as a native .csv file + this.ResponseFilters.Add((req, res, dto) => + { + if (req.ResponseContentType == ContentType.Csv) + { + res.AddHeader(HttpHeaders.ContentDisposition, + string.Format("attachment;filename={0}.csv", req.OperationName)); + } + }); + + +[ keys); + + //Retrieves the specified item from the cache. + T Get(string key); + + //Increments the value of the specified key by the given amount. + //The operation is atomic and happens on the server. + //A non existent value at key starts at 0 + long Increment(string key, uint amount); + + //Increments the value of the specified key by the given amount. + //The operation is atomic and happens on the server. + //A non existent value at key starts at 0 + long Decrement(string key, uint amount); + + //Adds a new item into the cache at the specified cache key only if the cache is empty. + bool Add(string key, T value); + + //Sets an item into the cache at the cache key specified regardless if it already exists or not. + bool Set(string key, T value); + + + //Replaces the item at the cachekey specified only if an items exists at the location already. + bool Replace(string key, T value); + + bool Add(string key, T value, DateTime expiresAt); + bool Set(string key, T value, DateTime expiresAt); + bool Replace(string key, T value, DateTime expiresAt); + + bool Add(string key, T value, TimeSpan expiresIn); + bool Set(string key, T value, TimeSpan expiresIn); + bool Replace(string key, T value, TimeSpan expiresIn); + + + //Invalidates all data on the cache. + void FlushAll(); + + //Retrieves multiple items from the cache. + //The default value of T is set for all keys that do not exist. + IDictionary GetAll(IEnumerable keys); + + + //Sets multiple items to the cache. + void SetAll(IDictionary values); + } + + +[ + { + if (req.ResponseContentType == ContentType.Csv) + { + res.AddHeader(HttpHeaders.ContentDisposition, + string.Format("attachment;filename={0}.csv", req.OperationName)); + } + }); + + +Note: **ServiceStack already does this for you** though it still serves a good example to show how you can plug-in your own custom format. If you wish, you can remove all custom formats with (inside AppHost.Configure()): + this.ContentTypeFilters.ClearCustomFilters(); + +The ability to automatically to register another format and provide immediate value and added functionality to all your existing web services (without any code-changes or configuration) we believe is a testament to ServiceStack's clean design of using strongly-typed 'message-based' DTOs to let you develop clean, testable and re-usable web services. No code-gen or marshalling is required to bind to an abstract method signature, every request and calling convention maps naturally to your web services DTOs. + + +## Usage +The CSV format is effectively a first-class supported format so everything should work as expected, including being registered as an available format on ServiceStack's metadata index page: + +* [/servicestack/metadata](http://www.servicestack.net/ServiceStack.MovieRest/servicestack/metadata) + +And being able to preview the output of a service: + +* [/servicestack/csv/metadata?op=Movie](http://www.servicestack.net/ServiceStack.MovieRest/servicestack/csv/metadata?op=Movie) + +By default they are automatically available using ServiceStack's standard calling conventions, e.g: + +* [/csv/syncreply/Movies](http://www.servicestack.net/ServiceStack.MovieRest/csv/syncreply/Movies) + +### REST Usage +CSV also works just as you would expect with user-defined RESTful urls, i.e. you can append ?format=csv to specify the format in the url e.g: + +* [/movies?format=csv](http://www.servicestack.net/ServiceStack.MovieRest/movies?format=csv) + +This is how the above web service output looks when opened up in [google docs](https://spreadsheets.google.com/pub?key=0AjnFdBrbn8_fdDBwX0Rha04wSTNWZDZlQXctcmp2bVE&hl=en_GB&output=html) + + +Alternative in following with the HTTP specification you can also specify content-type `"text/csv"` in the *Accept* header of your HttpClient, e.g: + + var httpReq = (HttpWebRequest)WebRequest.Create("http://mono.servicestack.net/ServiceStack.MovieRest/movies"); + httpReq.Accept = "text/csv"; + var csv = new StreamReader(httpReq.GetResponse().GetResponseStream()).ReadToEnd(); + + +## Limitations +As most readers familiar with the CSV format will know there are some inherent limitations with CSV-format namely it is a flat-structured tabular data format that really only supports serialization of a single result set. +This limitation remains, although as the choice of what to serialize is based on the following conventions: + +* If you only return one result in your DTO it will serialize that. +* If you return multiple results it will pick the first IEnumerable<> property or if it doesn't exist picks the first property. +* Non-enumerable results are treated like a single row. + +Basically if you only return 1 result it should work as expected otherwise it will chose the best candidate based on the rules above. + +The second major limitation is that it doesn't yet include a CSV deserializer (currently on the TODO list), so while you can view the results in CSV format you can't post data to your web service in CSV and have it automatically deserialize for you. You can however still upload a CSV file and parse it manually yourself. + +#Features +Unlike most CSV serializers that can only serialize rows of primitive values, the CsvSeriliaizer uses the [JSV Format](~/text-serializers/jsv-format) under the hood so even [complex types](https://spreadsheets.google.com/pub?key=0AjnFdBrbn8_fdG83eWdGM1lnVW9PMlplcmVDYWtXeVE&hl=en_GB&output=html) will be serialized in fields in a easy to read format - no matter how deep its hierarchy. + + +Feel free to discuss or find more about any of these features at the [Service Stack Google Group](https://groups.google.com/forum/#!forum/servicestack) + +[{jsondto} + +Because of the browser behavior of the script tag, you can embed any markup or javascript unescaped. +Unless it has none or a 'javascript' type attribute, the browser doesn't execute it letting you to access the contents with: + + document.getElementById('dto').innerHTML + +From there, javascript invoked just before the closing body tag (i.e. the fastest time to run DOM-altering javascript) which takes the data, +builds up a html string and injects the generated markup in the contents of the page. + +After the report is rendered, and because JavaScript can :) UX-friendly behaviors are applied to the document allowing the user to sort the table data on each column as well as providing an easy way to take a copy of the JSON data source. + +For what it does, the JavaScript is very terse considering no JavaScript framework was used. In most cases the JSON payload is a lot larger than the entire JavaScript used to render the report :) + +### Advantages of a strong-typed, code-first web service framework + +Although hard to believe, most of the above web service examples were developed before ServiceStack's CSV and HTML format existed. +No code-changes were required in order to take advantage of the new formats, they were automatically available after replacing the ServiceStack.dlls with the latest version (v1.81+) + +Being able to generically provide new features like this shows the advantage of ServiceStack's strong-typed, code-first approach to developing web services that lets you focus on your app-specific logic as you only need to return C#/.NET objects or throw C#/.NET exceptions which gets automatically handled, and hosted on a number of different endpoints in a variety of different formats. + +Out of the box REST, RPC and SOAP endpoints types are automatically provided, in JSON, XML, CSV, JSV and now the new HTML report format above. + +Follow [@demisbellot](http://twitter.com/demisbellot) and [@ServiceStack](http://twitter.com/ServiceStack) for twitter updates + + + +[("/todos") + .Add("/todos/{Id}"); + } + } + + + //REST Resource DTO + public class Todo + { + public long Id { get; set; } + public string Content { get; set; } + public int Order { get; set; } + public bool Done { get; set; } + } + + //Todo REST Service implementation + public class TodoService : RestServiceBase + { + public TodoRepository Repository { get; set; } //Injected by IOC + + public override object OnGet(Todo request) + { + if (request.Id != default(long)) + return Repository.GetById(request.Id); + + return Repository.GetAll(); + } + + //Called for both new and updated TODOs + public override object OnPost(Todo todo) + { + return Repository.Store(todo); + } + + public override object OnDelete(Todo request) + { + Repository.DeleteById(request.Id); + return null; + } + } + + +### Calling the above TODO REST service from any C#/.NET Client + //no code-gen required, can re-use above DTO's + + var restClient = new JsonServiceClient("http://localhost/Backbone.Todo"); + var all = restClient.Get>("/todos"); // Count = 0 + + var todo = restClient.Post("/todos", new Todo { Content = "New TODO", Order = 1 }); //todo.Id = 1 + all = restClient.Get>("/todos"); // Count = 1 + + todo.Content = "Updated TODO"; + todo = restClient.Post("/todos", todo); // todo.Content = Updated TODO + + restClient.Delete("/todos/" + todo.Id); + all = restClient.Get>("/todos"); // Count = 0 + + +### Calling the TODO REST service from jQuery + + $.getJSON("http://localhost/Backbone.Todo/todos", function(todos) { + alert(todos.length == 1); + }); + + +That's all the application code required to create a simple REST web service. + +##Live Demo of Backbone TODO app (running on Linux/MONO): + +**[http://www.servicestack.net/Backbone.Todos/](http://www.servicestack.net/Backbone.Todos/)** + +Preview links using just the above code sample with (live demo running on Linux): + +ServiceStack's strong-typed nature allows it to infer a greater intelligence of your web services and is able to provide a +host of functionality for free, out of the box without any configuration required: + + * Host on different formats and endpoints: [XML](http://www.servicestack.net/Backbone.Todos/todos?format=xml), + [JSON](http://www.servicestack.net/Backbone.Todos/todos?format=json), [JSV](http://www.servicestack.net/Backbone.Todos/todos?format=jsv), + [CSV](http://www.servicestack.net/Backbone.Todos/todos?format=csv) + + * [A HTML5 Report format to view your web services data in a human-friendly view](http://www.servicestack.net/Backbone.Todos/todos?format=html) + + * [An auto generated api metadata page, with links to your web service XSD's and WSDL's](http://www.servicestack.net/Backbone.Todos/metadata) + + + +Download +======== + +To start developing web services with Service Stack we recommend starting with the ServiceStack.Examples project (includes ServiceStack.dlls): + + * **[ServiceStack.Examples/downloads/](https://github.com/ServiceStack/ServiceStack.Examples/downloads)** + +If you already have ServiceStack and just want to download the latest release binaries get them at: + + * **[ServiceStack/downloads/](https://github.com/ServiceStack/ServiceStack/downloads)** + +Alternatively if you want keep up with the latest version you can always use the power of Git :) + + git clone git://github.com/ServiceStack/ServiceStack.git + +[Release notes for major releases](~/framework/release-notes) + +## Getting Started +Online tutorials that walks you through developing and calling web services is available here: + + * **[Read the documentation on the ServiceStack Wiki](~/framework/home)** + * [Creating a Hello World Web service](http://www.servicestack.net/ServiceStack.Hello/) + * [Calling Web Services from MonoTouch](http://www.servicestack.net/monotouch/remote-info/) + + +# Features of a modern web services framework + + Developed in the modern age, Service Stack provides an alternate, cleaner POCO-driven way of creating web services, featuring: + +### A DRY, strongly-typed 'pure model' REST Web Services Framework +Unlike other web services frameworks ServiceStack let's you develop web services using strongly-typed models and DTO's. +This lets ServiceStack and other tools to have a greater intelligence about your services allowing: + +- [Multiple serialization formats (JSON, XML, JSV and SOAP with extensible plugin model for more)](http://mono.servicestack.net/ServiceStack.Hello/servicestack/metadata) +- [A single re-usable C# Generic Client (In JSON, JSV, XML and SOAP flavors) that can talk to all your services.](https://github.com/ServiceStack/ServiceStack.Extras/blob/master/doc/UsageExamples/UsingServiceClients.cs) +- [Re-use your Web Service DTOs (i.e. no code-gen) on your client applications so you're never out-of-sync](https://github.com/ServiceStack/ServiceStack.Extras/blob/master/doc/UsageExamples/UsingServiceClients.cs) +- [Automatic serialization of Exceptions in your DTOs ResponseStatus](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceInterface/ServiceBase.cs#L154) +- [The possibility of a base class for all your services to put high-level application logic (i.e security, logging, etc)](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceInterface/ServiceBase.cs#L24) +- [Highly testable, your in-memory unit tests for your service can also be used as integration tests](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Tests/WebServicesTests.cs) +- [Built-in rolling web service error logging (if Redis is Configured in your AppHost)](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceInterface/ServiceBase.cs#L122) +- [Rich REST and HTML support on all web services with x-www-form-urlencoded & multipart/form-data (i.e. FORM posts and file uploads)](http://mono.servicestack.net/ServiceStack.Hello/) + +## Define web services following Martin Fowlers Data Transfer Object Pattern: + +Service Stack was heavily influenced by [**Martin Fowlers Data Transfer Object Pattern**](http://martinfowler.com/eaaCatalog/dataTransferObject.html): + +>When you're working with a remote interface, such as Remote Facade (388), each call to it is expensive. +>As a result you need to reduce the number of calls, and that means that you need to transfer more data +>with each call. One way to do this is to use lots of parameters. +>However, this is often awkward to program - indeed, it's often impossible with languages such as Java +>that return only a single value. +> +>The solution is to create a Data Transfer Object that can hold all the data for the call. It needs to be serializable to go across the connection. +>Usually an assembler is used on the server side to transfer data between the DTO and any domain objects. + +The Request and Response DTO's used to define web services in ServiceStack are standard `DataContract` POCO's while the implementation just needs to inherit from a testable and dependency-free `IService`. As a bonus for keeping your DTO's in a separate dependency-free .dll, you're able to re-use them in your C#/.NET clients providing a strongly-typed API without any code-gen what-so-ever. Also your DTO's *define everything* Service Stack does not pollute your web services with any additional custom artifacts or markup. + +Service Stack re-uses the custom artifacts above and with zero-config and without imposing any extra burden on the developer adds discover-ability and provides hosting of your web service on a number of different physical end-points which as of today includes: XML (+REST), JSON (+REST), JSV (+REST) and SOAP 1.1 / SOAP 1.2. + +### WCF the anti-DTO Web Services Framework +Unfortunately this best-practices convention is effectively discouraged by Microsoft's WCF SOAP Web Services framework as they encourage you to develop API-specific RPC method calls by mandating the use method signatures to define your web services API. This results in less re-usable, more client-specific APIs that encourages more remote method calls. + +Unhappy with this perceived anit-pattern in WCF, ServiceStack was born providing a Web Service framework that embraces best-practices for calling remote services, using config-free, convention-based DTO's. + + +### Full support for unit and integration tests +Your application logic should not be tied to a third party vendor's web service host platform. +In Service Stack they're not, your web service implementations are host and end-point ignorant, dependency-free and can be unit-tested independently of ASP.NET, Service Stack or its IOC. + +Without any code changes unit tests written can be re-used and run as integration tests simply by switching the IServiceClient used to point to a configured end-point host. + +### Built-in Funq IOC container +Configured to auto-wire all of your web services with your registered dependencies. +[Funq](http://funq.codeplex.com) was chosen for it's [high-performance](http://www.codeproject.com/Articles/43296/Introduction-to-Munq-IOC-Container-for-ASP-NET.aspx), low footprint and intuitive full-featured minimalistic API. + +### Encourages development of message-style, re-usable and batch-full web services +Entire POCO types are used to define the request and response DTO's to promote the creation well-defined coarse-grained web services. Message-based interfaces are best-practices when dealing with out-of-process calls as they are can batch more work using less network calls and are ultimately more re-usable as the same operation can be called using different calling semantics. This is in stark contrast to WCF's Operation or Service contracts which encourage RPC-style, application-specific web services by using method signatures to define each operation. + +As it stands in general-purpose computing today, there is nothing more expensive you can do than a remote network call. Although easier for the newbie developer, by using _methods_ to define web service operations, WCF is promoting bad-practices by encouraging them to design and treat web-service calls like normal function calls even though they are millions of times slower. Especially at the app-server tier, nothing hurts performance and scalability of your client and server than multiple dependent and synchronous web service calls. + +Batch-full, message-based web services are ideally suited in development of SOA services as they result in fewer, richer and more re-usable web services that need to be maintained. RPC-style services normally manifest themselves from a *client perspective* that is the result of the requirements of a single applications data access scenario. Single applications come and go over time while your data and services are poised to hang around for the longer term. Ideally you want to think about the definition of your web service from a *services and data perspective* and how you can expose your data so it is more re-usable by a number of your clients. + +### Cross Platform Web Services Framework +With Mono on Linux now reaching full-maturity, Service Stack runs on .NET or Linux with Mono and can either be hosted inside an ASP.NET Web Application, Windows service or Console application running in or independently of a Web Server. + +### Low Coupling for maximum accessibility and testability +No coupling between the transport's endpoint and your web service's payload. You can re-use your existing strongly-typed web service DTO's with any .NET client using the available Soap, Xml and Json Service Clients - giving you a strongly-typed API while at the same time avoiding the need for any generated code. + + * The most popular web service endpoints are configured by default. With no extra effort, each new web service created is immediately available and [discoverable](http://www.servicestack.net/ServiceStack.Examples.Host.Web/ServiceStack/Metadata) on the following end points: + * [XML (+REST)](http://www.servicestack.net/ServiceStack.Examples.Host.Web/ServiceStack/Xml/Metadata?op=GetFactorial) + * [JSON (+REST)](http://www.servicestack.net/ServiceStack.Examples.Host.Web/ServiceStack/Json/Metadata?op=GetFactorial) + * [JSV (+REST)](http://www.servicestack.net/ServiceStack.Examples.Host.Web/ServiceStack/Jsv/Metadata?op=GetFactorial) + * [SOAP 1.1](http://www.servicestack.net/ServiceStack.Hello/servicestack/soap11) + * [SOAP 1.2](http://www.servicestack.net/ServiceStack.Hello/servicestack/soap12) + * View the [Service Stack endpoints page](~/framework/history-of-webservices) for our recommendations on which endpoint to use and when. + +# High Performance Sub Projects +Also included in ServiceStack are libraries that are useful in the development of high performance web services: + + * [ServiceStack.Text](~/text-serializers/json-csv-jsv-serializers) - The home of ServiceStack's JSON and JSV text serializers, the fastest text serializers for .NET + * [JsonSerializer](http://www.servicestack.net/mythz_blog/?p=344) - The fastest JSON Serializer for .NET. Over 3 times faster than other .NET JSON serialisers. + * [TypeSerializer](~/text-serializers/json-csv-jsv-serializers) - The JSV-format, a fast, compact text serializer that is very resilient to schema changes and is: + * 3.5x quicker and 2.6x smaller than the .NET XML DataContractSerializer and + * 5.3x quicker and 1.3x smaller than the .NET JSON DataContractSerializer - _[view the detailed benchmarks](http://www.servicestack.net/benchmarks/NorthwindDatabaseRowsSerialization.1000000-times.2010-02-06.html)_ + + * [ServiceStack.Redis](~/redis-client/redis-client) - An API complete C# [Redis](http://code.google.com/p/redis/) client with native support for persisting C# POCO objects. + * You can download the latest [RedisWindowsDownload Windows build for the Redis Server here]. + * [Redis Admin UI](http://www.servicestack.net/mythz_blog/?p=381) - An Ajax GUI admin tool to help visualize your Redis data. + + * [OrmLite](~/ormlite/ormlite-overview) - A convention-based, configuration free lightweight ORM that uses attributes from DataAnnotations to infer the table schema. Currently supports both Sqlite and SqlServer. + + * [Caching](~/framework/caching-options) - A common interface for caching with providers for: + * Memcached + * In Memory Cache + * Redis + + +## Find out More + * Twitter: to get updates of ServiceStack, follow [@demisbellot](http://twitter.com/demisbellot) or [@ServiceStack](http://twitter.com/ServiceStack) on twitter. + * Email any questions to _demis.bellot@gmail.com_ + +## Future Roadmap +Service Stack is under continuous improvement and is always adding features that are useful for high-performance, scalable and resilient web service scenarios. This is the current road map but is open to change. +If you have suggestions for new features or want to prioritize the existing ones below: [http://code.google.com/p/servicestack/issues/entry you can leave feedback here]. + + * Add an opt-in durable Message Queue service processing of [AsyncOneWay] requests (with In Memory, Redis and RabbitMQ implementations) + * Enable [ProtoBuf.NET](http://code.google.com/p/protobuf-net/), TypeSerializer and CSV (for tabular datasets) web service endpoints + * Integrate the Spark View Engine and enable a HTML endpoint so web services can also return a HTML human-friendly view + * New REST web service endpoint developed in the 'Spirit of REST' with partitioning of GET / POST / PUT / DELETE requests and utilizing 'Accept mimetype' HTTP request header to determine the resulting content type. + * Code generated proxy classes for Objective-C, Java Script / Action Script (and Java or C++ if there's enough interest) clients. + * Develop a completely managed HTTP Web Service Host (at the moment looking at building on top of [Kayak HTTP](http://kayakhttp.com)) + * Add support for 'Web Sockets' protocol + +## Similar open source projects +Similar Open source .NET projects for developing or accessing web services include: + + * Open Rasta - RESTful web service framework: + * [http://trac.caffeine-it.com/openrasta](http://trac.caffeine-it.com/openrasta) + + * Rest Sharp - an open source REST client for .NET + * [http://restsharp.org](http://restsharp.org) + + +## Troubleshooting + +For IIS 6.0-only web servers (i.e. without IIS 7 and compatibility-mode) IIS and ASP.NET requires mapping an extension in order to embed ServiceStack. You can use a default handled ASP.NET extension like *.ashx e.g. + + + +Which will change your urls will now look like: + + http://localhost/servicestack.ashx/xml/syncreply/Hello?Name=World + + + +*** + +Runs on both Mono and .NET 3.5. _(Live preview hosted on Mono / CentOS)_ + diff --git a/src/Docs/framework/release-notes.md b/src/Docs/framework/release-notes.md new file mode 100644 index 00000000..d6e52517 --- /dev/null +++ b/src/Docs/framework/release-notes.md @@ -0,0 +1,617 @@ +#ServiceStack 3.09 Release Notes + +## Latest version of Dapper built-in + +Now in ServiceStack is StackOverflow's own [benchmark leading](http://www.servicestack.net/benchmarks/) Micro ORM **[Dapper](http://code.google.com/p/dapper-dot-net/)**. +This means a fresh NuGet install of ServiceStack now includes the 2 fastest Micro ORMS for .NET! :) + +OrmLite and Dapper are very similar in design in that they're simply useful extension methods on ADO.NET's `System.Data.*` interfaces, the difference being Dapper has extension methods of `IDbConnection` whilst OrmLite methods hangs off the lower `IDbCommand`. And because they both make use of 'clean POCOs' - they can be used interchangeably together on the same DB connection. This also allows them to both make use of `OrmLiteConnectionFactory` to configure connection manager over your DB ConnectionString. + +## Mvc Mini Profiler now baked in + +We've made ServiceStack's [HTML5 JSON Report Format](https://github.com/ServiceStack/ServiceStack/wiki/HTML5ReportFormat) even better by now including the excellent [Mvc Mini Profiler](http://code.google.com/p/mvc-mini-profiler/) - by [@jarrod_dixon](https://twitter.com/jarrod_dixon) and [@samsaffron](https://twitter.com/samsaffron). +It's the same profiler used to profile and help speed up sites like [Stack Overflow](http://www.stackoverflow.com) and more recently the much faster [NuGet v2.0](http://nuget.org) website. + +As the MVC Mini Profiler is optimized for a .NET 4.0 MVC app, we've made some changes in order to integrate it into ServiceStack: + + - Make it work in .NET 3.0 by backporting .NET 4.0 classes into **ServiceStack.Net30** namespace (Special thanks to OSS! :) + - Using Mono's **ConcurrentDictionary** classes + - Using [Lokad.com's Tuples](http://code.google.com/p/lokad-shared-libraries/source/browse/Source/Lokad.Shared/Tuples/Tuple.cs) + - Switched to using ServiceStack's much faster [Json Serializer](http://www.servicestack.net/docs/text-serializers/json-serializer) + - Reduced the overall footprint by replacing the use of jQuery and jQuery.tmpl with a much smaller [jquip (jQuery-in-parts)](https://github.com/mythz/jquip) dependency. + - Moved to the **ServiceStack.MiniProfiler** namespace and renamed to **Profiler** to avoid clashing with another Mvc Mini Profiler in the same project + +As a side-effect of integrating the Mvc Mini Profiler all ServiceStack .NET 3.0 projects can make use of .NET 4.0's ConcurrentDictionary and Tuple support, hassle free! + +### Using the MVC Mini Profiler + +Just like the [Normal Mvc Mini Profiler](http://code.google.com/p/mvc-mini-profiler/) you can enable it by starting it in your Global.asax, here's how to enable it for local requests: + + protected void Application_BeginRequest(object src, EventArgs e) + { + if (Request.IsLocal) + Profiler.Start(); + } + + protected void Application_EndRequest(object src, EventArgs e) + { + Profiler.Stop(); + } + +That's it! Now every time you view a web service in your browser (locally) you'll see a profiler view of your service broken down in different stages: + +![Hello MiniProfiler](http://www.servicestack.net/files/miniprofiler-hello.png) + +By default you get to see how long it took ServiceStack to de-serialize your request, run any Request / Response Filters and more importantly how long it took to **Execute** your service. + +The profiler includes special support for SQL Profiling that can easily be enabled for OrmLite and Dapper by getting it to use a Profiled Connection using a ConnectionFilter: + + this.Container.Register(c => + new OrmLiteConnectionFactory( + "~/App_Data/db.sqlite".MapHostAbsolutePath(), + SqliteOrmLiteDialectProvider.Instance) { + ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current) + }); + +Refer to the [Main MVC MiniProfiler home page](http://code.google.com/p/mvc-mini-profiler/) for instructions on how to configure profiling for Linq2Sql and EntityFramework. + +It's also trivial to add custom steps enabling even finer-grained profiling for your services. +Here's a [simple web service DB example](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Services/ProfilerService.cs) +returning a list of Movies using both a simple DB query and a dreaded N+1 query. + + public class MiniProfiler + { + public string Type { get; set; } + } + + public class MiniProfilerService : ServiceBase + { + public IDbConnectionFactory DbFactory { get; set; } + + protected override object Run(MiniProfiler request) + { + var profiler = Profiler.Current; + + using (var dbConn = DbFactory.OpenDbConnection()) + using (var dbCmd = dbConn.CreateCommand()) + using (profiler.Step("MiniProfiler Service")) + { + if (request.Type == "n1") + { + using (profiler.Step("N + 1 query")) + { + var results = new List(); + foreach (var movie in dbCmd.Select()) + { + results.Add(dbCmd.QueryById(movie.Id)); + } + return results; + } + } + + using (profiler.Step("Simple Select all")) + { + return dbCmd.Select(); + } + } + } + } + +Calling the above service normally provides the following Profiler output: + +![Simple DB Example](http://www.servicestack.net/files/miniprofiler-simpledb.png) + +Whilst calling the service with the **n1** param yields the following warning: + +![Simple N+1 DB Example](http://www.servicestack.net/files/miniprofiler-simpledb-n1.png) + +In both cases you see the actual SQL statements performed by clicking the **SQL** link. The N+1 query provides shows the following: + +![N+1 DB Example SQL Statements](http://www.servicestack.net/files/miniprofiler-simpledb-n1-sql.png) + +Notice the special attention the MVC MiniProfiler team put into identifying **Duplicate** queries - Thanks Guys! + + +## Download v3.09 + + * **[Using Nuget to add ServiceStack to an existing ASP.NET or MVC application](http://nuget.org/packages/ServiceStack)** + * [Download ServiceStack.Examples projects and Starter Templates](https://github.com/ServiceStack/ServiceStack.Examples/downloads) + * [Download just the ServiceStack.dlls binaries](https://github.com/ServiceStack/ServiceStack/downloads) + * [Other ServiceStack projects available on NuGet](http://www.servicestack.net/docs/framework/nuget) + +. + +Follow [@demisbellot](http://twitter.com/demisbellot) and [@ServiceStack](http://twitter.com/ServiceStack) for twitter updates + +***** + +##ServiceStack 2.28 Release Notes + +This release includes a few enhancements and catches up on all the pull requests and most of the issues that were submitted +since the last release. + +## ServiceStack is now using Trello.com for features/issue tracking +ServiceStack now hosts and tracks its new issues and feature requests on a +[live public Trello dash board](https://trello.com/board/servicestack-features-bugs/4e9fbbc91065f8e9c805641c) where anyone +is welcome to add to, or simply check the progress of their features/issues in the work queue. + +## Special Thanks to Contributors +We now have a special [contributor page](https://github.com/ServiceStack/ServiceStack/blob/master/CONTRIBUTORS.md) +and section on the [main project page](https://github.com/ServiceStack/ServiceStack) showing the many contributors to ServiceStack's +projects over the years. We hope we haven't missed anyone out - please send us a pull request if you would like to be added. + +The major features in this release include: + +## Redis MQ Client/Server +A redis-based message queue client/server that can be hosted in any .NET or ASP.NET application. The **RedisMqHost** lives in the +[ServiceStack.Redis](https://github.com/ServiceStack/ServiceStack.Redis) project and brings the many benefits of using a Message Queue. +The current unoptimized version uses only a single background thread although initial benchmarks shows it can +send/receive a promising **4.6k messages /sec** when accessing a local redis instance (on my dev workstation). + +Major kudos goes to [Redis](http://redis.io) which thanks to its versatility, has Pub/Sub and Lists primitives that makes implementing a Queue trivial. + +The first version already sports the major features you've come to expect from a MQ: + + - Each service maintains its own Standard and Priority MQ's + - Automatic Retries on messages generating errors with Failed messages sent to a DLQ (Dead Letter Queue) when its Retry threshold is reached. + - Each message can have a ReplyTo pointing to any Queue, alternatively you can even provide a ServiceStack endpoint URL which will + send the response to a Web Service instead. If the web service is not available it falls back into publishing it in the default + Response Queue so you never lose a message! + - MQ/Web Services that don't return any output have their Request DTOs sent to a rolling **Out** queue which can be monitored + by external services (i.e. the publisher/caller) to determine when the request has been processed. + +Although you can host **RedisMqHost** in any ASP.NET web app, the benefit of hosting inside ServiceStack is that your +**web services are already capable** of processing Redis MQ messages **without any changes required** since they're already effectively +designed to work like a Message service to begin with, i.e. **C# POCO-in -> C# POCO-out**. + +This is another example of ServiceStack's prescribed DTO-first architecture continues to pay dividends since each web service is a DI clean-room +allowing your **C# logic to be kept pure** as it only has to deal with untainted POCO DTOs, allowing your same web service to be re-used in: +SOAP, REST (JSON,XML,JSV,CSV,HTML) web services, view models for dynamic HTML pages and now as a MQ service! + +Eventually (based on feedback) there will be posts/documentation/examples forthcoming covering how to use it, in the meantime +you can [Check out the Messaging API](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Messaging/IMessageService.cs) +to see how simple it is to use. To see some some working code showing some of the capabilities listed above, +[view the tests](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/RedisMqHostTests.cs). + +Hooking up a basic send/reply example is as easy as: + + //DTO messages: + public class Hello { public string Name { get; set; } } + public class HelloResponse { public string Result { get; set; } } + + var redisFactory = new PooledRedisClientManager("localhost:6379"); + var mqHost = new RedisMqHost(redisFactory, noOfRetries:2, null); + + //Server - MQ Service Impl: + mqHost.RegisterHandler(m => + new HelloResponse { Result = "Hello, " + m.GetBody().Name }); + mqHost.Start(); + + ... + + //Client - Process Response: + mqHost.RegisterHandler(m => { + Consle.Log("Received: " + m.GetBody().Result); + }); + mqHost.Start(); + + ... + + //Producer - Start publishing messages: + var mqClient = mqHost.CreateMessageQueueClient(); + mqClient.Publish(new Hello { Name = "ServiceStack" }); + + +## JSON/JSV Serializers now supports Abstract/Interface and object types +We're happy to report the most requested feature for ServiceStack's JSON/JSV serializers is now available at: +[ServiceStack.Text v2.28](https://github.com/ServiceStack/ServiceStack.Text/downloads). + +The JSON and JSV Text serializers now support serializing and deserializing DTOs with **Interface / Abstract or object types**. +Amongst other things, this allows you to have an IInterface property which when serialized will include its concrete type information in a +**__type** property field (similar to other JSON serializers) which when serialized populates an instance of that +concrete type (provided it exists). + +Likewise you can also have polymorphic lists e.g. of a base **Animal** type and be populated with a **Cats** and **Dogs** which should now deserialize correctly. + +As always performance was a primary objective when adding this feature, and as a result we should have a well performing implementation of it. + +Note: This feature is **automatically** added to all **Abstract/Interface/Object** types, i.e. you **don't** need to include any +`[KnownType]` attributes to take advantage of it. + +## Other features/fixes: + + - Added JSON/JSV custom serialization behavior injection of BCL value types in e.g: [JsConfig](https://github.com/ServiceStack/ServiceStack.Text/blob/master/src/ServiceStack.Text/JsConfig.cs#L16) + - Serialization errors now return 400 status code + - Add option to propagate errors instead of being sent in the response [Tymek Majewski](https://github.com/letssellsomebananas) + - Added UserAgent to IHttpRequest type + - Add useful overloads to HttpResult class + - SetPermantentCookie/SetSessionCookie/SetCookie + - LastModified + - Fix compression bug in `RequestContext.ToOptimizedResult()` + - byte[] responses are written directly to the response stream with the ContentType: application/octet-stream + +***** + +##ServiceStack 2.20 Release Notes + +### New Markdown Razor View Engine +The biggest feature in this release is the new Markdown support built-into ServiceStack and more +specifically its **Markdown Razor View Engine**. Markdown Razor is an MVC Razor-inspired templating +engine that allows you to generate dynamic Markdown and HTML using plain Markdown and Razor Sytnax. + +View the new [Markdown Razor Introduction](http://www.servicestack.net/docs/markdown/markdown-razor) +for more information. + +### ServiceStack.Docs Website Released +The first website to take advantage of the new Markdown templating support in ServiceStack is +**[http://www.servicestack.net/docs](http://www.servicestack.net/docs)** which is effectively built entirely +using ServiceStack's GitHub project Markdown wiki and README.md pages. To render the entire website +the transformed Markdown content is merged with a static **default.shtml** website template. + +A nice feature of a Markdown-enabled website is that since the Content is decoupled from the website +template we are easily able to enhance the site using Ajax to load partial content page loads. This +provides a faster browsing experience since the entire webpage doesn't have to be reloaded. + +See the [About ServiceStack Docs Website](http://www.servicestack.net/docs/markdown/about) for more +information. + +### MonoTouch support in ServiceStack C# Clients +Support was added to the Generic JSON and JSV ServiceStack C# Clients to work around MonoTouch's +No-JIT Restrictions. Unfortunately to do this we've had to create a new MonoTouch Build +configuration which doesn't use any C# Expressions or Reflection.Emit. So you need to download the +MonoTouch ServiceStack builds for running in MonoTouch. +**[Download MonoTouch-v2.20.zip](https://github.com/ServiceStack/ServiceStack/tree/master/release/latest/MonoTouch)** + +An example MonoTouch project that uses these Sync and Async C# ServiceClients to talk to the +[RestFiles](www.servicestack.net/RestFiles/) web services is in the +[RestFilesClient Example project](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/MonoTouch/RestFilesClient). + +## Other Features + + - Added support for [IContainerAdapter](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Configuration/IContainerAdapter.cs) to let you [plug-in and use different IOC Containers](https://groups.google.com/d/topic/servicestack/A-W9scHaEBA/discussion) + - Allow alternate strategies [for resolving Service Types](https://groups.google.com/d/topic/servicestack/Sb7Rcnhte-E/discussion) + - If your IService implements IDisposable, it will be disposed straight after it's been executed. + + +#ServiceStack 2.09 Release Notes + +## ServiceStack is now on NuGet! + +As we have received a number of requests to provide NuGet packages for ServiceStack and its components, we're now happy to say we're now NuGet compliant! Where a configured and working ServiceStack web framework is just 1 NuGet command away :) + +[![Install-Package ServiceStack](http://mono.servicestack.net/img/nuget-servicestack.png)](~/framework/nuget) + +This will add the ServiceStack dlls to your standard VS.NET ASP.NET Web Application, Register ServiceStack handler in your Web.Config, configure your AppHost and create both a **[Hello](http://mono.servicestack.net/ServiceStack.Hello/)** and a fully-operational **[TODO REST service](http://mono.servicestack.net/Backbone.Todos/)**. + +Together with just 2 static content files ([default.htm](https://github.com/ServiceStack/ServiceStack/blob/master/NuGet/ServiceStack/content/default.htm) and [jqunback-1.51.js](https://github.com/AjaxStack/AjaxStack)) you get a fully configured and working RESTful application (*which as an aside benefit we hope encourages .NET developers into the [beautiful world of Backbone.js](http://documentcloud.github.com/backbone/) and Single Page Ajax Applications*). + +The NuGet package of ServiceStack is essentially the **RootPath** Starter Template. The other starting templates, e.g. Windows Service, Console Hosts, hosting ServiceStack at custom /api paths are still available in the [ServiceStack.Examples downloads](https://github.com/ServiceStack/ServiceStack.Examples/downloads). + +Check **[ServiceStack's NuGet page](~/framework/nuget)** for the full description of the available ServiceStack packages on NuGet.org + +## ServiceStack Overview and Create REST services slides released! + +Although this normally shouldn't warrant a release line item, for the technology focused - it's actually hard work :) +We believe the overview slides provide the best starting point for new developers looking to find out the benefits of ServiceStack and how they can easily develop REST services with it. Today, we're releasing the following 2 slides: + +### [ServiceStack Overview and Features](https://docs.google.com/present/view?id=dg3mcfb_208gv3kcnd8) +[![Install-Package ServiceStack](http://mono.servicestack.net/img/slides-01-overview-300.png)](https://docs.google.com/present/view?id=dg3mcfb_208gv3kcnd8) + +### [Creating REST Web Services](https://docs.google.com/present/view?id=dg3mcfb_213gsvvmmfk) +[![Install-Package ServiceStack](http://mono.servicestack.net/img/slides-02-create-rest-service-300.png)](https://docs.google.com/present/view?id=dg3mcfb_213gsvvmmfk) + +## Better configuration + +### ASP.NET MVC-like Route API to define user-defined REST paths + +In your AppHost Configure() script you can register paths against your Request DTOs with the **Routes** property like so: + + Routes + .Add("/hello") + .Add("/hello/{Name*}") + .Add("/todos") + .Add("/todos/{Id}"); + +This is an alternative to the `[Route("/hello")]` attribute which was previously required on your Request DTOs. +They should work as expected, where any match will route that request to the designated service. All variables enclosed with `{Id}` will be populated on the selected Request DTO with that value of the path component. + +`Routes.Add("/hello/{Name*}")` is a special case that matches every path beginning with **/hello/** where the **Hello** Request DTOs **Name** property is populated with the contents of the remaining url path. E.g. /hello/**any/path/here** will be populated in Hello.`{Name}` property. + +### Disable ServiceStack-wide features + +Sometimes the ServiceStack default of having all endpoints and formats all wired up correctly without any configuration is actually not preferred (we know, enterprises right? :), so in this release we've made it easy to turn on and off system-wide features using simple enum flags. To simplify configuration we also added some useful Enum extensions (Has,Is,Add,Remove) to make it easier to signal your intent with Enums. + +E.g. this is how you would disable 'JSV' and 'SOAP 1.1 & 1.2' endpoints: + + var disableFeatures = Feature.Jsv | Feature.Soap; + SetConfig(new EndpointHostConfig + { + EnableFeatures = Feature.All.Remove(disableFeatures), + }); + + +***** + +##ServiceStack 2.08 - ServiceStack meets Backbone.js + +Unlike in previous releases, the ServiceStack framework itself has largely remained unchanged. This update is focused towards including [Backbone.js](http://documentcloud.github.com/backbone/) into ServiceStack.Examples project. + +[Backbone.js](http://documentcloud.github.com/backbone/) is a beautifully-designed and elegant light-weight JavaScript framework that allows you to build you're Ajax applications separated into **Views** and **Models** connected via key-value data-binding and declarative custom event handling. Of special interest to us is its ability to supply a url and have it **automatically connect your Models** with your **Backend REST services**, which we're happy to report works well with ServiceStack's JSON services. + +From the [author](http://twitter.com/jashkenas) of the popular and game-changing libraries [CoffeeScript](http://jashkenas.github.com/coffee-script/) and [Underscore.js](http://documentcloud.github.com/underscore/) - Backbone.js differentiates itself from other javascript frameworks in that it promotes a clean separation of concerns and a modular application design, which is hard to achieve with other frameworks that couple themselves too tightly with the DOM. + +## Backbone's TODO + +Our first action was porting Backbone's example TODO app and replace its HTML5 localStorage backend with a ServiceStack REST + Redis one. This was quite easy to do and we were happy that [resulting C# server code for the REST backend](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/Backbone.Todos/Global.asax.cs) ended up weighing in at less than the size of VS.NET's default Web.config file :) + +Like the rest of our examples a **[live demo is available](http://mono.servicestack.net/Backbone.Todos/)**. + +### TODO app now in all Starter templates + +As the Backbone TODO app represented a small, but working REST client and server we decided to make it the default app in **all** of ServiceStack's Starter Templates. + +That's right, your Starting template for your **Enterprise Windows Service now comes with a useful TODO app out-of-the-box!** We rightfully believe this makes it the coolest app provided in any starting project template :) + +## ServiceStack was built to serve Ajax applications + +At this point it's a good time to re-iterate that ServiceStack was designed from the start to be a first-class Ajax server that provides best support for HTML5 Ajax/SPA apps, purely because we believe it to be the future application delivery platform that provides the broadest reach and best user experience possible. We've made special efforts to provide the [fastest JSON web services possible for .NET](http://www.servicestack.net/mythz_blog/?p=344), with a [first-class redis client](~/redis-client/redis-client) and a [strong caching story](~/framework/caching-options) important in developing high-performance web services and a responsive end user experience. + +***** + +## ServiceStack 2.07 - Q/A Release - Finding Web.Config Nirvana :) + +This release was focused on finding the perfect Web.Config that best allows ServiceStack to work consistently everywhere across all ASP.NET and HttpListener hosts on both .NET and MONO platforms. +A primary goal of ServiceStack is to be able to build web services once and use the same binaries and App .config files to run everywhere in every ASP.NET or HttpListener host on Windows with .NET or on OSX/Linux with MONO. + +Since your services are POCO message-based and only need to be implement an `IService` interface your services effectively operate in a *clean-room* [DDD Service](http://en.wikipedia.org/wiki/Domain-driven_design), and have a potential for re-use in a variety of other hosts, i.e. Message Queues, Windows services, Windows applications, etc. + +### Running cross-platform +Although the promise of the .NET architecture allows for pure C# applications to run on every .NET platform, the ASP.NET hosts don't always share the same compatibility levels as there are subtle differences in implementation and behaviour amongst the various ASP.NET hosts. + +The only real way of ensuring ServiceStack runs well in each environment is to actually setup an environment on each host with each configuration we want to support. Unfortunately this time-consuming process is a necessary one in order to limit any new regressions from being introduced as a result of added features. + +## New ServiceStack Starter Templates projects released +So with that in mind, included in this release is the 'StartTemplates' solution providing the same Hello World Web service hosted in every supported mode and configurations. +There are now 2 supported modes in which to run ServiceStack: + +##### a) Do not require an existing Web Framework - Host from the root path: `/` +##### b) Use ServiceStack with an existing Web Framework - Host web services at a user-defined: `/custompath` + +### Starter Template projects + +The new StarterTemplates in the [ServiceStack.Examples GitHub project](https://github.com/ServiceStack/ServiceStack.Examples/) provide a good starting template for each supported configuration below: + + * [.NET 3.5](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/StarterTemplates/ApiPath35) and [.NET 4.0](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/StarterTemplates/CustomPath40) - ASP.NET Custom Path: **/api** + * [.NET 3.5](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/StarterTemplates/RootPath35) and [.NET 4.0](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/StarterTemplates/RootPath40) - ASP.NET Root Path: **/** + * [Windows Service w/ HttpListener](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/StarterTemplates/WinServiceAppHost) + * [Stand alone Console App Host w/ HttpListener](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/StarterTemplates/ConsoleAppHost) + +We're happy to report the above configurations are well supported on Windows with .NET visible by the **[Latest Windows Integration Test Reports](http://www.servicestack.net/testreports/2011-03-09_RunReports-Windows.htm)** showing ServiceStack running correctly on IIS 3.5,4.0/WebDev Server 2.0,4.0/Windows Service/Console Application hosts. + +To deploy on MONO you can just XCOPY/SFTP the files across as-is (i.e. as compiled with VS.NET) to your Linux or OSX server. In most of the scenarios it works as-is however the integration tests have uncovered a couple of known issues visible in the **[Latest Linux Integration Test Reports](http://www.servicestack.net/testreports/2011-03-15_RunReports-Linux.htm)**. + +### Known issues on MONO: + + * Depending on your setup a url with a trailing path '/' will cause Nginx/FastCGI or Apache/mod_mono to request a /default.aspx which if it doesn't exist will return a 404 + * If you want to use a custom path i.e. **/api** your ASP.NET virtual path also needs to start with your httpHandler path. Which is why an ASP.NET application hosted on **/ApiPath35/api** works as expected whilst one at **/CustomPath35/api** does not. + + +## Eating our own dog food +### ServiceStack.NET now running example projects on both Nginx/FastCGI and Apache/mod_mono on the same server + +With a few Linux admin tweaks to add and assign a new virtual network interface with a new IP Address, we're easily able to run both Nginx/FastCGI and Apache/mod_mono HTTP servers on the same server, both configured to point to ServiceStack ASP.NET GitHub Example Projects. + +[[http://www.servicestack.net]] is running Nginx/FastCGI configuration while the sub domain [[http://api.servicestack.net]] is running Apache/mod_mono (the recommended MONO ASP.NET configuration). + +Here are links to ServiceStack.Example projects on both Nginx and Apache: + + * [Nginx](http://www.servicestack.net/ServiceStack.Hello/) - [Apache](http://api.servicestack.net/ServiceStack.Hello/) /ServiceStack.Hello + * [Nginx](http://www.servicestack.net/RestFiles/) - [Apache](http://api.servicestack.net/RestFiles/) /RestFiles/ + * [Nginx](http://www.servicestack.net/RedisStackOverflow/) - [Apache](http://api.servicestack.net/RedisStackOverflow/) /RedisStackOverflow/ + * [Nginx](http://www.servicestack.net/RedisStackOverflow/) - [Apache](http://api.servicestack.net/RedisStackOverflow/) /RedisStackOverflow/ + * [Nginx](http://www.servicestack.net/ServiceStack.MovieRest/) - [Apache](http://api.servicestack.net/ServiceStack.MovieRest/) /ServiceStack.MovieRest/ + * [Nginx](http://www.servicestack.net/ServiceStack./) - [Apache](http://api.servicestack.net/ServiceStack.Northwind/) /ServiceStack.Northwind/ + +We plan to create more wiki pages walking through how to setup your own ASP.NET web applications on Linux with MONO. + +If you have a preference on what hosting environment you would like to see ServiceStack running in (e.g. AppHarbor, Moncai, Amazon, Azure, SuseStudio, etc), we'd love to hear from you, please post your preference to [ServiceStack's Google Group](http://groups.google.com/group/servicestack) + +***** + +## ServiceStack v2.0 + +The ServiceStack code-base has gone under a re-structure to better support user contributions, testing, fine-grained deployments allowing hosting of ServiceStack in 32 and 64 bit servers, in medium or full trust hosting environments. + +The changes from a high-level are: + + * No more ILMERGE.exe dlls, all ServiceStack .dlls now map 1:1 with a project of the same name + * As a result all .pdb's for all assemblies are now included in each release to help debugging (this was lost using ILMERGE) + * When not using OrmLite/Sqlite, ServiceStack is a full .NET managed assembly with no P/Invokes that can run in 32/64 bit hosts + * All projects upgraded to VS.NET 2010 (min baseline is still .NET 3.5) + * Non-core, high-level functionality has been moved into a new [ServiceStack.Contrib](~/contrib/servicestack-contrib) + +## Breaking Changes +A lot of effort was made to ensure that clients would not be affected i.e. no code-changes should be required. + +As a result of the change to the deployment dlls where previously ServiceStack.dll was an ILMERGED combination of every implementation dll in ServiceStack. You will now need to explicitly reference each dll that you need. + +To help visualize the dependencies between the various components, here is a tree showing which dependencies each project has: + + * [ServiceStack.Text.dll](~/text-serializers/json-csv-jsv-serializers) + * [ServiceStack.Interfaces.dll](https://github.com/ServiceStack/ServiceStack/tree/master/src/ServiceStack.Interfaces) + + * [ServiceStack.Common.dll](https://github.com/ServiceStack/ServiceStack/tree/master/src/ServiceStack.Common) + + * [ServiceStack.dll](https://github.com/ServiceStack/ServiceStack/tree/master/src/ServiceStack) + * [ServiceStack.ServiceInterface.dll](https://github.com/ServiceStack/ServiceStack.Contrib/tree/master/src/ServiceStack.ServiceInterface) + + * [ServiceStack.Redis.dll](~/redis-client/redis-client) + * [ServiceStack.OrmLite.dll](~/ormlite/ormlite-overview) + + +### Non-core Framework features extracted into new ServiceStack.Contrib project + +In the interest of promoting contributions and modifications from the community, the non-core projects of ServiceStack has been extracted into a new user contributed **ServiceStack.Contrib** project site at: + +**[[https://github.com/ServiceStack/ServiceStack.Contrib]]** + +I invite all ServiceStack users who want to share their generic high-level functionality and useful app-specific classes under this project where the rest of the community can benefit from. + +***** + +## Service Stack 1.82 Release Notes + +### [New HTML5 Report Format Added](~/framework/json-report-format) + +The biggest feature added in this release is likely the new HTML5 report format that generates a human-readable HTML view of your web services response when viewing it in a web browser. +Good news is, like the [[ServiceStack-CSV-Format]] it works with your existing web services as-is, with no configuration or code-changes required. + +[![HTML5 Report Format](http://mono.servicestack.net/img/HTML5Format.png)](~/framework/json-report-format) + +Here are some results of web services created before the newer HTML5 and CSV formats existed: + + * **RedisStackOverflow** [Latest Questions](http://mono.servicestack.net/RedisStackOverflow/questions) + * **RestMovies** [All Movie listings](http://mono.servicestack.net/ServiceStack.MovieRest/movies) + * **RestFiles** [Root Directory](http://mono.servicestack.net/RestFiles/files) + +Use the **?format=[json|xml|html|csv|jsv]** to toggle and view the same web service in different formats. + +### New ServiceStack.Northwind Example project added + +In order to be able to better demonstrate features with a 'real-world' DataSet, a new ServiceStack.Northwind project has been added which inspects the Northwind dataset from an SQLite database. +A live demo is hosted at [[http://mono.servicestack.net/ServiceStack.Northwind/]]. Here are some links below to better demonstrate the new HTML format with a real-world dataset: + +#### Northwind Database REST web services + * [All Customers](http://mono.servicestack.net/ServiceStack.Northwind/customers) + * [Customer Detail](http://mono.servicestack.net/ServiceStack.Northwind/customers/ALFKI) + * [Customer Orders](http://mono.servicestack.net/ServiceStack.Northwind/customers/ALFKI/orders) + + +### Improved Caching + +ServiceStack has always had its own (i.e. ASP.NET implementation-free) [good support for caching](~/framework/caching-options), though like most un-documented features it is rarely used. The caching has been improved in this version to now support caching of user-defined formats as well. Here is example usage from the new Northwind project: + + public class CachedCustomersService : RestServiceBase + { + public ICacheClient CacheClient { get; set; } + + public override object OnGet(CachedCustomers request) + { + return base.RequestContext.ToOptimizedResultUsingCache( + this.CacheClient, "urn:customers", () => { + var service = base.ResolveService(); + return (CustomersResponse) service.Get(new Customers()); + }); + } + } + +The above code caches the most optimal output based on browser capabilities, i.e. if your browser supports deflate compression (as most do), a deflated, serialized output is cached and written directly on the response stream for subsequent calls. Only if no cache exists will the web service implementation (e.g lambda) be executed, which populates the cache before returning the response. + +To see the difference caching provides, here are cached equivalents of the above REST web service calls: + +#### Northwind Database **Cached** REST web services + * [All Customers](http://mono.servicestack.net/ServiceStack.Northwind/cached/customers) + * [Customer Detail](http://mono.servicestack.net/ServiceStack.Northwind/cached/customers/ALFKI) + * [Customer Orders](http://mono.servicestack.net/ServiceStack.Northwind/cached/customers/ALFKI/orders) + + +### API Changes + +The underlying IHttpRequest (an adapter interface over ASP.NET/HttpListener HTTP Requests) can now be retrieved within your web service to be able to query the different HTTP Request properties: + + var httpReq = base.RequestContext.Get(); + +Also added is the ability to resolve existing web services (already auto-wired by the IOC) so you can re-use existing web service logic. Here is an example of usage from the Northwind [CustomerDetailsService.cs](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/ServiceStack.Northwind/ServiceStack.Northwind.ServiceInterface/CustomerDetailsService.cs). + + var ordersService = base.ResolveService(); + var ordersResponse = (OrdersResponse)ordersService.Get(new Orders { CustomerId = customer.Id }); + + +## Service Stack 1.79 Release Notes + +### The C#/.NET Sync and Async Service Clients were improved to include: + * Enhanced REST functionality and access, now more succinct than ever + * Uploading of files to ServiceStack web services using **HTTP POST** *multipart/form-data* + * More robust error handling support handling C# exceptions over REST services + * For examples of on how to use the C# REST client API check out the tests in the new REST Files project: + * [Sync C# client examples](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RestFiles/RestFiles.Tests/SyncRestClientTests.cs) + * [Async C# client examples](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RestFiles/RestFiles.Tests/AsyncRestClientTests.cs) + +## New RestFiles project added to [ServiceStack.Examples](https://github.com/ServiceStack/ServiceStack.Examples/) GitHub project: +#### Live demo available at: [servicestack.net/RestFiles/](http://mono.servicestack.net/RestFiles/) + + * Provides a complete remote file system management over a [RESTful api](http://mono.servicestack.net/RestFiles/servicestack/metadata) + * The complete RESTful /files web service implementation is only [**1 C# page class**](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RestFiles/RestFiles.ServiceInterface/FilesService.cs) + * Includes a pure Ajax client to provide a **GitHub-like** file browsing experience, written in only [**1 static HTML page, using only jQuery**](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RestFiles/RestFiles/default.htm) + * [C# integration test examples](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RestFiles/RestFiles.Tests/) are also included showing how to access this RESTful api over sync and async C# clients + +Read the rest of the [Rest Files README.md](https://github.com/ServiceStack/ServiceStack.Examples/tree/master/src/RestFiles/RestFiles) for a more detailed overview about the project. + + +## Service Stack 1.78 Release Notes + + * Added more tests and fixed bugs in ServiceStack's new CSV format and Request/Response filters + * Added new information on the generated web service index, individual web service page now include: + * REST paths (if any are defined) thanks to [@jakescott](http://twitter.com/jakescott) + * Included directions to consumers on how to override the HTTP **Accept** header and specify the **format** + * Now including any System.CompontentModel.**Description** meta information attributed on your Request DTO + * Preview the new documentation pages on ServiceStack [**Hello**](http://www.servicestack.net/ServiceStack.Hello/servicestack/json/metadata?op=Hello) and [**Movies**](http://www.servicestack.net/ServiceStack.MovieRest/servicestack/xml/metadata?op=Movie) example web service pages. + * Added [tests to show how to implement Basic Authentication](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/RequestFiltersTests.cs) using the new RequestFilters + * Changed the httpHandler paths in the Example projects and [created a new Config class](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.WebHost.Endpoints/SupportedHandlerMappings.cs) to store which supported mappings go with which web servers + middleware. + * Provide a way to register new urls for different ServiceStack handler mappings used, e.g. to register IIS 6.0 urls: + + SetConfig(new EndpointConfig { ServiceEndpointsMetadataConfig = ServiceEndpointsMetadataConfig.GetForIis6ServiceStackAshx() }); + + +## Service Stack 1.77 Release Notes + +This release was focused to opening up ServiceStack to better support adding more hooks and extension points where new formats can be added. The CSV format was also added to test these new extension APIs. + +## Main features added in this release: + +* Added support for the [CSV format](~/framework/csv-format) +* Enhanced the IContentTypeFilter API to add support for different serialization formats +* Added Request and Response filters so custom code can inspect and modify the incoming [IHttpRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceHost/IHttpRequest.cs) or [IHttpResponse](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceHost/IHttpResponse.cs). +* Added `Request.Items` so you can share arbitrary data between your filters and web services. +* Added `Request.Cookies` for reading cookies (to avoid retrieving it from HttpRuntime.Current) +* Removed the preceding UTF8 BOM character to ServiceStack's JSON and JSV Serializers. +* All features above are available on both ASP.NET and HttpListener hosts + +### [CSV Format](~/framework/csv-format) + +Using the same tech that makes [ServiceStack's JSV and JSON serializers so fast](http://www.servicestack.net/benchmarks/NorthwindDatabaseRowsSerialization.100000-times.2010-08-17.html) (i.e. no run-time reflection, static delegate caching, etc), should make it the fastest POCO CSV Serializer available for .NET. + +The 'CSV' format is the first format added using the new extensions API, which only took the following lines of code: + + //Register the 'text/csv' content-type and serializers (format is inferred from the last part of the content-type) + this.ContentTypeFilters.Register(ContentType.Csv, + CsvSerializer.SerializeToStream, CsvSerializer.DeserializeFromStream); + + //Add a response filter to add a 'Content-Disposition' header so browsers treat it as a native .csv file + this.ResponseFilters.Add((req, res, dto) => + { + if (req.ResponseContentType == ContentType.Csv) + { + res.AddHeader(HttpHeaders.ContentDisposition, + string.Format("attachment;filename={0}.csv", req.OperationName)); + } + }); + +With only the code above, the 'CSV' format is now a first-class supported format which means all your existing web services can take advantage of the new format without any config or code changes. Just drop the latest ServiceStack.dlls (v1.77+) and you're good to go! + +Note: there are some limitations on the CSV format and implementation which you can read about on the [ServiceStack CSV Format page](~/framework/csv-format). + +### Request and Response Filters: + +The Request filter takes a IHttpRequest, IHttpResponse and the **Request DTO**: + List> RequestFilters { get; } + +The Response filter takes a IHttpRequest, IHttpResponse and the **Response DTO**: + List> ResponseFilters{ get; } + +Note: both sets of filters are called before there any output is written to the response stream so you can happily use the filters to authorize and redirect the request. Calling `IHttpResponse.Close()` will close the response stream and stop any further processing of this request. + +Feel free to discuss or find more about any of these features at the [Service Stack Google Group](https://groups.google.com/forum/#!forum/servicestack) + + +[a:contains("' + title + '")')[0]; + if (el) el.parentNode.className = 'active'; +} \ No newline at end of file diff --git a/src/Docs/logging/logging-overview.md b/src/Docs/logging/logging-overview.md new file mode 100644 index 00000000..af464b87 --- /dev/null +++ b/src/Docs/logging/logging-overview.md @@ -0,0 +1,45 @@ +## ServiceStack.Logging an implementation-free logging interface for your app logic to bind to +For twitter updates follow @demisbellot or @ServiceStack + +Even in the spirit of **Bind to interfaces, not implementations**, many .NET projects still have +a hard dependency to [log4net](http://logging.apache.org/log4net/index.html). + +Although log4net is the standard for logging in .NET, potential problems can arise from your libraries having a hard dependency on it: + +* Your library needs to be shipped with a third-party dependency +* Potential conflicts can occur when different libraries have dependency on different versions of log4net (e.g. the 1.2.9 / 1.2.10 dependency problem). +* You may want to use a different logging provider (i.e. network distributed logging) +* You want your logging for Unit and Integration tests to redirect to the Console or Debug logger without any configuration. + +ServiceStack.Logging solves these problems by providing an implementation-free ILog interface that your application logic can bind to +where your Application Host project can bind to the concrete logging implementation at deploy or runtime. + +ServiceStack.Logging also includes adapters for the following logging providers: + +* Log4Net 1.2.10+ +* Log4Net 1.2.9 +* EventLog +* Console Log +* Debug Log +* Null / Empty Log + +# Usage Examples + +Once on your App Startup, either In your AppHost.cs or Global.asax file inject the concrete logging implementation that your app should use, e.g. + +## Log4Net + LogManager.LogFactory = new Log4NetFactory(true); //Also runs log4net.Config.XmlConfigurator.Configure() + +## Event Log + LogManager.LogFactory = new EventLogFactory("ServiceStack.Logging.Tests", "Application"); + +Then your application logic can bind to and use a lightweight implementation-free ILog which at runtime will be an instance of the concrete implementation configured in your host: + + ILog log = LogManager.GetLogger(GetType()); + + log.Debug("Debug Event Log Entry."); + log.Warn("Warning Event Log Entry."); + + + + diff --git a/src/Docs/markdown/about.md b/src/Docs/markdown/about.md new file mode 100644 index 00000000..23cec54f --- /dev/null +++ b/src/Docs/markdown/about.md @@ -0,0 +1,45 @@ + +**ServiceStack Docs** is a collection of all documentation scattered amongst all of ServiceStack's Open source +projects hosted together in a single website. It's also the first website to showcase ServiceStack's +new support of the Markdown format where the website's content is composed entirely of static Markdown +pages collected from the project's README.md and wiki Markdown pages spread in GitHub. + +# ServiceStack Docs Features + +### Static Templates +All content pages simply consist of a static Markdown page merged together with a static +**default.shtml** page where its variable place holders are replaced with evaluated Markdown content. + +### Partial Content +On the header of each content page there are links to view the raw [HTML content only](?format=html.bare) +or [Markdown only](?format=text.bare) of the current page outside of the website template. + +### Non-invasive Ajax-enhanced web experience +To show how to take advantage of the partial-content support in ServiceStack, browsers +that support the **history.pushState** API have enhanced behavior applied to them where +links to other parts of the website are done via non-obtrusive partial page loads. + +This improves browsing experience performance since the browser only has to load the content html +and not the entire web page. By not reloading the page we are able to control the pages transitions +where in our case we sprinkle a little jQuery to apply a simple slide and fade effect between pages. + +### Dynamic content with Markdown Razor +Although most of this website is static it contains a couple of dynamic pages that makes use of the new +Markdown Razor View engine template in ServiceStack. The [Search](~/search/Redis) +and [Category](~/category/Redis%20Client) web services both have +view templates which when defined take over the **html format** for that REST service. Unlike other +web frameworks these dynamic pages are **first-class web services** where you can optionally use +REST clients to consume these services in JSON, XML, ... formats e.g. here are the above pages in JSON: + + - [/search/Redis?format=json](~/search/Redis?format=json) + - [/category/Redis Client?format=json](~/category/Redis%20Client?format=json) + +### Extensible output +Each markdown page is configured to inherit from the **CustomMarkdownPage.cs** base class which is used to +generate the **dynamic sidebar** based on the context of the currently viewed page. Other metadata like +the **Title**, **Category** and document **Date** are also added and displayed in the static website template. + +### Find out more about Markdown support + + - [Markdown Features](markdown-features) - Benefits and Markdown features in ServiceStack + - [Markdown Razor](markdown-razor) - Introduction to the new Markdown View Engine and its Razor syntax in ServiceStack \ No newline at end of file diff --git a/src/Docs/markdown/markdown-features.md b/src/Docs/markdown/markdown-features.md new file mode 100644 index 00000000..91973ca2 --- /dev/null +++ b/src/Docs/markdown/markdown-features.md @@ -0,0 +1,78 @@ +# Benefits of Markdown + +Benefits of Markdown includes that it focuses exclusively on **marking up structured content** that as a +result is not tied to its containing website. This makes it easy to re-use and host Markdown content in +multiple outputs (i.e. alt websites, emails, pdfs, etc). It's also very easy to read and write and thus +we believe it is the premier document format where most content should be stored in. + +#First class support of Markdown in ServiceStack v2.10 +Because of its many inherent benefits, ServiceStack now includes first-class support for the Markdown +format. Which now features: + +### Static website templating +Static Markdown pages can be fused together with a static **default.shtml** page to create websites +based solely on static Markdown and html pages (as done in this site). + +### Performance +On startup, all Markdown pages (.md) are parsed and converted to html and pre-cached in memory for +fast response times. Although pages are cached, modified pages are detected and re-evaluated and +**Last-Modified** Cache HTTP Headers are returned to be able to avoid unnecessary page loads. + +### Clean Urls +You can omit the extension (.md) to the Markdown urls to request a specific page. +Allowing a clean url structure using just directory and file names. + +### Partial Content +The raw HTML and Markdown text of each page (without the website template) is available by appending +the following to the query string: + + - [?format=html.bare](?format=html.bare) - View content only in html + - [?format=text.bare](?format=text.bare) - View content only in Markdown + +Apart from making your content more accessible and re-usable it also allows you to provide partial content +updates which is a popular technique amongst high performance websites. + +# Markdown View templating engine +We love Markdown so much we've added a templating view engine so you can dynamically generate Markdown +and HTML content with a view engine inspired by ASP.NET's Razor syntax and features. + +The Mardown Razor template engine works much like ASP.NET MVC's Razor although instead of Controllers, +the templates make use of the model (aka DTOs) returned from your web services. +This allows you to non-invasively provide customized HTML representations for your existing +web services by simply adding a razor page anywhere in the **/Views** directory. + +This is a key feature in ServiceStack's implementation where apart from being easily able to generate +a dynamic HTML page, you can, **without any effort** also access the XML, JSON, JSV and CSV formats of that service. + +The resolution order ServiceStack's uses to resolve the appropriate Markdown template to use for rendering HTML output is: + + 1. If the Web Service specifies a template (via a customized IHttpResult.**TemplateName** response) - then a View with that name. + 2. A view with the same name as the Response DTO, looking first in **/Views** then in **/Views/Shared** + 3. A view with the same name as the Request DTO, looking first in **/Views** then in **/Views/Shared** + +Markdown Razor templates are simply normal plain-text Markdown pages that support dynamic behavior by +using the familiar syntax of MVC's Razor i.e. all statements prefixed with the familiar @ symbol. + +#### Static website template +Once the appropriate view is executed it's output is stored in the **'Body'** variable and is merged with its +static website template. The rules for finding the appropriate master website template is simple: +It's the first **default.shtml** page it can find, looking first in its current working directory then +recursively up the directory hierarchy until it finds one. + +The view is merged with the static website template by replacing all **<--@VarName-->** with variables +generated by the page (i.e. in ScopeArgs). i.e. the executed output of the View is stored in the **Body** +variable and is embedded in the static website template by replacing all **<--@Body-->** found. + +### Same old Raxor Syntax and features +We've made a considerable effort in trying to keep syntax parity with MVC's Razor that we've even pulled +across MVC's HtmlHelper (and its connected classes) so that the **HtmlHelper** extension methods can be +easily ported across. This is what enables MVC to access strong-typed features like: + +**@Html.TextBoxFor(m => m.FirstName)** + +Which renders the same output as it does in MVC Razor (since we're using their code to do this :) + +Out of the box we've pulled across the extension methods for Html.**Display**XXX, Html.**Input**XXX, +Html.**Label**XXX and Html.**TextArea**XXX although you can bring and use your own extensions in your pages. + +For more information on the features and syntax supported checkout **[Introduction to Markdown Razor](markdown-razor)** diff --git a/src/Docs/markdown/markdown-razor.md b/src/Docs/markdown/markdown-razor.md new file mode 100644 index 00000000..4f7b8dc9 --- /dev/null +++ b/src/Docs/markdown/markdown-razor.md @@ -0,0 +1,416 @@ +See other [Markdown Features](markdown-features) in ServiceStack and how this website +makes use of them in [About Docs](about). + +# Introducing the new Markdown Razor View Engine!! + +Markdown Razor is the first HTML and Text (i.e. Markdown) view engine built into ServiceStack. +The pages are simply plain-text Markdown surrounded by MVC Razor-like syntax to provide +its enhanced dynamic functionality. + +## Extensible with custom base classes and Helpers +Markdown Razor is extensible in much the same way as MVC Razor is with the ability to define and +use your own **custom base class**, **Helpers** and **HtmlHelper** extension methods. +This allows you to call util methods on your base class or helpers directly from your templates. + +You can define a base class for all your markdown pages by implementing **MarkdownViewBase** and +register it in your AppHost with: + + SetConfig(new EndpointHostConfig { + WebHostUrl = "http://mono.servicestack.net/docs", //Replace prefix with the Url supplied + MarkdownBaseType = typeof(CustomMarkdownPage), //Set base class for all Markdown pages + MarkdownGlobalHelpers = new Dictionary { + {"Ext", typeof(CustomStaticHelpers)} //Define global Helpers e.g. at Ext. + } + }); + +If a **WebHostUrl** is specified, it replaces all **~/** in all static website and Markdown +pages with it. The **MarkdownGlobalHelpers** allow you to define global helper methods +available to all your pages. This has the same effect of declaring it in your base class e.g: + + public class CustomMarkdownPage : MarkdownViewBase { + public CustomStaticHelpers Ext = new CustomStaticHelpers(); + } + +Which you can access in your pages via **@Ext.MyHelper(Model)**. Declaring instance methods on +your custom base class allows you to access them without any prefix. + +## MarkdownViewBase base class +By default the **MarkdownViewBase** class provides the following properties and hooks: + + public class MarkdownViewBase { + + public IAppHost AppHost; //Access Config, resolve dependencies, etc. + public MarkdownPage MarkdownPage; //This precompiled Markdown page with Metadata + public HtmlHelper Html; //ASP.NET MVC's HtmlHelper + public bool RenderHtml; //Flag to on whether you should you generate HTML or Markdown + + /* + All variables passed to and created by your page. + The Response DTO is stored and accessible via the 'Model' variable. + + All variables and outputs created are stored in ScopeArgs which is what's available + to your website template. The Generated page is stored in the 'Body' variable. + */ + public Dictionary ScopeArgs; + + //Called before page is executed + public virtual void InitHelpers(){} + + //Called after page is executed before it's merged with the website template if any + public virtual void OnLoad(){} + } + +See this websites +**[CustomMarkdownPage.cs](https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/Docs/Docs.Logic/CustomMarkdownPage.cs)** +base class for an example on how to effectively use the base class to Resolve dependencies, +inspect generated variables, generate **PagesMenu** and other dynamic variables for output +in the static website template. + +# Compared with ASP.NET MVC Razor Syntax + +For the best way to illustrate the similarities with ASP.NET MVC Razor syntax I will show examples +of the Razor examples in [@ScottGu's](http://twitter.com/scottgu) introductory +[Introducing "Razor" - a new view engine for ASP.NET](http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx) + +Note: more context and the output for each snippet and example displayed is contained in the +[Introductory Example](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.ServiceHost.Tests/Formats/IntroductionExampleTests.cs) +and +[Introductory Layout](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.ServiceHost.Tests/Formats/IntroductionLayoutTests.cs) +Unit tests. For reference most features of Mardown Razor view engine are captured in the +[Core Template Unit Tests](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.ServiceHost.Tests/Formats/TemplateTests.cs) + +### Hello World Sample with Razor + + +The following basic page: + +![Hello World Output](http://weblogs.asp.net/blogs/scottgu/image_thumb_0E9E3527.png) + + +Can be generated in MVC Razor with: + +![Hello World MVC Razor](http://weblogs.asp.net/blogs/scottgu/image_3276E6B4.png) + + +And Markdown Razor with: + + # Razor Example + + ### Hello @@name, the year is @@DateTime.Now.Year + + Checkout [this product](/Product/Details/@@productId) + +### Loops and Nested HTML Sample + +The simple loop example: + +![Simple Loop Output](http://weblogs.asp.net/blogs/scottgu/image_thumb_155D5078.png) + + +With MVC Razor: + +![Simple Loop MVC Razor](http://weblogs.asp.net/blogs/scottgu/image_thumb_39360205.png) + + +With Markdown Razor: + + @@foreach (var p in products) { + - @@p.Name: (@@p.Price) + } + +### Parens-Free +At this point I think it would be a good to introduce some niceties in Markdown Razor of its own. +Borrowing a page out of [@BrendanEich](http://twitter.com/BrendanEich) proposal for +[CoffeeScript's](http://jashkenas.github.com/coffee-script/) inspired +[Parens free syntax](http://brendaneich.com/2010/11/paren-free/) for JS.Next - you can simply +remove the parens from all block statements e.g: + + @@foreach var p in products { + - @@p.Name: (@@p.Price) + } + +Produces the same output, and to go one step further you can remove the redundant **var** as well :) + + @@foreach p in products { + - @@p.Name: (@@p.Price) + } + +Which makes the Markdown Razor's version a bit more wrist-friendly then its MVCs cousin :) + +### If-Blocks and Multi-line Statements + +#### If statements in MVC Razor: +![If Statements](http://weblogs.asp.net/blogs/scottgu/image_thumb_4C76B8A4.png) + +#### If statements in Markdown Razor: + + @@if (products.Count == 0) { + Sorry - no products in this category + } else { + We have products for you! + } + +#### Multi-line and Multi-token statements +![MVC Razor Multi-line statements](http://weblogs.asp.net/blogs/scottgu/image_thumb_4B321FC5.png) + +Markdown Razor doesn't support multi-line or multi-token statements, instead you are directed to +take advantage for variable syntax declarations, e.g: + +#### Markdown replacement for Multi-line Statements + + @@var number = 1 + @@var message = ""Number is "" + number + + Your Message: @@message + + +### Integrating Content and Code + +Does it break with email addresses and other usages of @ in HTML? + +#### With MVC Razor +![MVC Razor Content and Code](http://weblogs.asp.net/blogs/scottgu/image_22B33DB1.png) + +#### With Markdown Razor + + Send mail to scottgu@microsoft.com telling him the time: @@DateTime.Now. + +Both View engines generate the expected output, e.g: + +![MVC Razor Content and Code Output](http://weblogs.asp.net/blogs/scottgu/image_thumb_20963EE8.png) + + +### Identifying Nested Content + +#### With MVC Razor +![MVC Razor Identifying Nested Content](http://weblogs.asp.net/blogs/scottgu/image_thumb_4A2A0A1B.png) + +#### With Markdown Razor + + @@if (DateTime.Now.Year == 2011) { + If the year is 2011 then print this + multi-line text block and + the date: @@DateTime.Now + } + +Markdown Razor doesn't need to do anything special with text blocks since all it does is look +for the ending brace '}'. This means if you want to output a brace literal '{' then you have to +double escape it with '{{' or '}}'. + +### HTML Encoding +Markdown Razor follows MVC Markdown behavior where by default content emitted using a @@ block +is automatically HTML encoded to better protect against XSS attack scenarios. + +If you want to avoid HTML Encoding you have the same options as MVC Razor where you can wrap your +result in **@@Html.Raw(htmlString)** or if you're using an Extension method simply return a +**MvcHtmlString** instead of a normal string. + +Markdown also lets you mix and match HTML in your markdown although any markdown between the tags +does not get converted to HTML. To tell Markdown Razor to evaluate the contents inside html +**<tag>...</tag>**'s need to prefixed with `^`, e.g. +(taken from the [/Views/Search.md](https://raw.github.com/ServiceStack/ServiceStack.Examples/master/src/Docs/Views/Search.md) page): + + ^
    + + @@foreach page in Model.Results { + ### @@page.Category > [@@page.Name](@@page.AbsoluteUrl) + @@page.Content + } + + ^
    + +If we didn't prefix `^` we would see `### @@page.Category ...` repeating. + +# Layout/MasterPage Scenarios - The Basics + +Markdown Razor actually deviates a bit from MVC Razor's handling of master layout pages and +website templates (we believe for the better :). + +### Simple Layout Example + +#### MVC Razor's example of a simple website template +![MVC Razor simple website template](http://weblogs.asp.net/blogs/scottgu/image_thumb_55CF2B80.png) + +Rather then using a magic method like `@@RenderBody()` we treat the output Body of View as just +another variable storing the output a in a variable called **'Body'**. This way we use the +same mechanism to embed the body like any other variable i.e. following the place holder convention +of **<--@@VarName-->** so to embed the View page output in the above master template you +would do: + + + + + Simple Site + + + +
    + Home + About +
    + +
    + +
    + + + + +By default we use convention to select the appropriate website template for the selected view +where it uses the nearest **default.shtml** static template it finds, looking first in the +current directory than up parent directories. + +Your View page names must be unique but can live anywhere in your **/View** directory so you are +free to structure your website templates and view pages accordingly. If for whatever reason you +need more granularity in selecting website templates than we provide similar options to MVC for +selecting a custom template: + +#### Select Custom Template with MVC Razor +![MVC Razor Custom Layout Page](http://weblogs.asp.net/blogs/scottgu/image_thumb_3B228F67.png) + +#### With Markdown Razor + + @@Layout ~/websiteTemplate + + # About this Site + + This is some content that will make up the ""about"" + page of our web-site. We'll use this in conjunction + with a layout template. The content you are seeing here + comes from ^^^websiteTemplate. + + And obviously I can have code in here too. Here is the + current date/year: @@DateTime.Now.Year + +Note: In addition to **@@Layout** we also support the more appropriate alias of **@@template**. + +## Layout/MasterPage Scenarios - Adding Section Overrides + +MVC Razor allows you to define **sections** in your view pages which you can embed in your +Master Template: + +#### With MVC Razor: +![MVC Razor Sections in Views](http://weblogs.asp.net/blogs/scottgu/image_thumb_448B2810.png) + +And you use in your website template like so: +![MVC Razor use Sections](http://weblogs.asp.net/blogs/scottgu/image_thumb_6D0A0A24.png) + +#### With Markdown Razor: +Markdown Razor supports the same **@@section** construct but allows you to embed it in your template +via the standard variable substitution convention, e.g: + + @@Layout ~/websiteTemplate + + # About this Site + + This is some content that will make up the ""about"" + page of our web-site. We'll use this in conjunction + with a layout template. The content you are seeing here + comes from ^^^websiteTemplate. + + And obviously I can have code in here too. Here is the + current date/year: @@DateTime.Now.Year + + @@section Menu { + - About Item 1 + - About Item 2 + } + + @@section Footer { + This is my custom footer for Home + } + +And these sections and body can be used in the website template like: + + + + + Simple Site + + + + + +
    + +
    + +
    + +
    + + + + + + +## Encapsulation and Re-Use with HTML Helpers + +In order to encapsulate and better be able to re-use HTML Helper utils MVC Razor includes a few +different ways to componentized and re-use code with HTMLHelper extension methods and declarative helpers. + +### Code Based HTML Helpers + +#### HtmlHelper extension methods with MVC Razor: +![MVC Razor HtmlHelper extension methods](http://weblogs.asp.net/blogs/scottgu/image_thumb_150C9377.png) + +Since we've ported MVC's HtmlHelper and its **Label**, **TextBox** extensions we can do something +similar although to make this work we need to inherit from the **MarkdownViewBase<TModel>** +generic base class so we know what Model to provide the strong-typed extensions for. You can do this +using the **@@model** directive specifying the full type name: + + @@model ServiceStack.ServiceHost.Tests.Formats.Product +
    + Edit Product + +
    + @@Html.LabelFor(m => m.ProductID) +
    +
    + @@Html.TextBoxFor(m => m.ProductID) +
    +
    + +Whilst we ported most of MVC HtmlHelper extension methods as-is, we did rip out all the validation +logic which appeared to be unnecessarily complex and too coupled with MVC's code-base. + +Note: Just as it is in MVC the **@@model** directive is a shorthand (which Markdown Razor also supports) for: + +**@@inherits Namespace.BaseType<Namespace.ModelType>** + +Whilst we don't support MVC Razors quasi C# quasi-html approach of defining declarative helpers, +we do allow you to on a per instance basis (or globally) import helpers in custom Fields using the +**@@helper** syntax: + + @@helper Prod: MyHelpers.ExternalProductHelper + +
    + All Products + @@Prod.ProductTable(Model) +
    (); + this.Addresses = new Dictionary(); + } + + [AutoIncrement] // Creates Auto primary key + public int Id { get; set; } + + public string FirstName { get; set; } + public string LastName { get; set; } + + [Index(Unique = true)] // Creates Unique Index + public string Email { get; set; } + + public Dictionary PhoneNumbers { get; private set; } //Blobbed + public Dictionary Addresses { get; private set; } //Blobbed + public DateTime CreatedAt { get; set; } + } + + public class Order { + + [AutoIncrement] + public int Id { get; set; } + + [References(typeof(Customer))] //Creates Foreign Key + public int CustomerId { get; set; } + + [References(typeof(Employee))] //Creates Foreign Key + public int EmployeeId { get; set; } + + public Address ShippingAddress { get; set; } //Blobbed (no Address table) + + public DateTime? OrderDate { get; set; } + public DateTime? RequiredDate { get; set; } + public DateTime? ShippedDate { get; set; } + public int? ShipVia { get; set; } + public decimal Freight { get; set; } + public decimal Total { get; set; } + } + + public class OrderDetail { + + [AutoIncrement] + public int Id { get; set; } + + [References(typeof(Order))] //Creates Foreign Key + public int OrderId { get; set; } + + public int ProductId { get; set; } + public decimal UnitPrice { get; set; } + public short Quantity { get; set; } + public decimal Discount { get; set; } + } + + public class Employee { + public int Id { get; set; } + public string Name { get; set; } + } + + public class Product { + public int Id { get; set; } + public string Name { get; set; } + public decimal UnitPrice { get; set; } + } + + //Setup SQL Server Connection Factory + var dbFactory = new OrmLiteConnectionFactory( + @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\App_Data\Database1.mdf;Integrated Security=True;User Instance=True", + SqlServerOrmLiteDialectProvider.Instance); + + //Use in-memory Sqlite DB instead + //var dbFactory = new OrmLiteConnectionFactory( + // ":memory:", false, SqliteOrmLiteDialectProvider.Instance); + + //Non-intrusive: All extension methods hang off System.Data.* interfaces + IDbConnection dbConn = dbFactory.OpenDbConnection(); + IDbCommand dbCmd = dbConn.CreateCommand(); + + //Re-Create all table schemas: + dbCmd.DropTable(); + dbCmd.DropTable(); + dbCmd.DropTable(); + dbCmd.DropTable(); + dbCmd.DropTable(); + + dbCmd.CreateTable(); + dbCmd.CreateTable(); + dbCmd.CreateTable(); + dbCmd.CreateTable(); + dbCmd.CreateTable(); + + dbCmd.Insert(new Employee { Id = 1, Name = "Employee 1" }); + dbCmd.Insert(new Employee { Id = 2, Name = "Employee 2" }); + var product1 = new Product { Id = 1, Name = "Product 1", UnitPrice = 10 }; + var product2 = new Product { Id = 2, Name = "Product 2", UnitPrice = 20 }; + dbCmd.Save(product1, product2); + + var customer = new Customer + { + FirstName = "Orm", + LastName = "Lite", + Email = "ormlite@servicestack.net", + PhoneNumbers = + { + { PhoneType.Home, "555-1234" }, + { PhoneType.Work, "1-800-1234" }, + { PhoneType.Mobile, "818-123-4567" }, + }, + Addresses = + { + { AddressType.Work, new Address { Line1 = "1 Street", Country = "US", State = "NY", City = "New York", ZipCode = "10101" } }, + }, + CreatedAt = DateTime.UtcNow, + }; + dbCmd.Insert(customer); + + var customerId = dbCmd.GetLastInsertId(); //Get Auto Inserted Id + customer = dbCmd.QuerySingle(new { customer.Email }); //Query + Assert.That(customer.Id, Is.EqualTo(customerId)); + + //Direct access to System.Data.Transactions: + using (var trans = dbCmd.BeginTransaction(IsolationLevel.ReadCommitted)) + { + var order = new Order + { + CustomerId = customer.Id, + EmployeeId = 1, + OrderDate = DateTime.UtcNow, + Freight = 10.50m, + ShippingAddress = new Address { Line1 = "3 Street", Country = "US", State = "NY", City = "New York", ZipCode = "12121" }, + }; + dbCmd.Save(order); //Inserts 1st time + + order.Id = (int)dbCmd.GetLastInsertId(); //Get Auto Inserted Id + + var orderDetails = new[] { + new OrderDetail + { + OrderId = order.Id, + ProductId = product1.Id, + Quantity = 2, + UnitPrice = product1.UnitPrice, + }, + new OrderDetail + { + OrderId = order.Id, + ProductId = product2.Id, + Quantity = 2, + UnitPrice = product2.UnitPrice, + Discount = .15m, + } + }; + + dbCmd.Insert(orderDetails); + + order.Total = orderDetails.Sum(x => x.UnitPrice * x.Quantity * x.Discount) + order.Freight; + + dbCmd.Save(order); //Updates 2nd Time + + trans.Commit(); + } + +Running this against a SQL Server database will yield the results below: + +[![SQL Server Management Studio results](http://www.servicestack.net/files/ormlite-example.png)](http://www.servicestack.net/files/ormlite-example.png) + +Notice the POCO types are stored in the [very fast](http://www.servicestack.net/mythz_blog/?p=176) +and [Versatile](http://www.servicestack.net/mythz_blog/?p=314) +[JSV Format](https://github.com/ServiceStack/ServiceStack.Text/wiki/JSV-Format) which although hard to do - +is actually more compact, human and parser-friendly than JSON :) + +# API Overview + +The API is minimal, providing basic shortcuts for the primitive SQL statements: + +[![OrmLite API](http://www.servicestack.net/files/ormlite-api.png)](http://www.servicestack.net/files/ormlite-api.png) + +Nearly all extension methods hang off the implementation agnostic `IDbCommand`. + +`CreateTable` and `DropTable` create and drop tables based on a classes type definition (only public properties used). + +For a one-time use of a connection, you can query straight of the `IDbFactory` with: + + var customers = DbFactory.Run(dbCmd => dbCmd.Where(new { Age = 30 })); + +The **Select** methods allow you to construct Sql using C# `string.Format()` syntax. +If you're SQL doesn't start with a **SELECT** statement, it is assumed a WHERE clause is being provided, e.g: + + var tracks = dbCmd.Select("Artist = {0} AND Album = {1}", "Nirvana", "Heart Shaped Box"); + +The same results could also be fetched with: + + var tracks = dbCmd.Select("select * from track WHERE Artist = {0} AND Album = {1}", "Nirvana", "Heart Shaped Box"); + +**Select** returns multiple records + + List tracks = dbCmd.Select() + +**Single** returns a single record + + Track track = dbCmd.Single("RefId = {0}", refId) + +**GetDictionary** returns a Dictionary made from the first to columns + + Dictionary trackIdNamesMap = dbCmd.GetDictionary("select Id, Name from Track") + +**GetLookup** returns an `Dictionary>` made from the first to columns + + var albumTrackNames = dbCmd.GetLookup("select AlbumId, Name from Track") + +**GetFirstColumn** returns a List of first column values + + List trackNames = dbCmd.GetFirstColumn("select Name from Track") + +**GetScalar** returns a single scalar value + + var trackCount = dbCmd.GetScalar("select count(*) from Track") + +All **Insert**, **Update**, and **Delete** methods take multiple params, while `InsertAll`, `UpdateAll` and `DeleteAll` take IEnumerables. +**GetLastInsertId** returns the last inserted records auto incremented primary key. + +`Save` and `SaveAll` will Insert if no record with **Id** exists, otherwise it Updates. +Both take multiple items, optimized to perform a single read to check for existing records and are executed within a single transaction. + +Methods containing the word **Each** return an IEnumerable and are lazily loaded (i.e. non-buffered). + +Selection methods containing the word **Query** or **Where** use parameterized SQL (other selection methods do not). +Anonymous types passed into **Where** are treated like an **AND** filter. + + var track3 = dbCmd.Where(new { AlbumName = "Throwing Copper", TrackNo = 3 }) + +**Query** statements take in parameterized SQL using properties from the supplied anonymous type (if any) + + var track3 = dbCmd.Query("select * from Track Where AlbumName = @album and TrackNo = @trackNo", + new { album = "Throwing Copper", trackNo = 3 }) + +GetById(s), QueryById(s), etc provide strong-typed convenience methods to fetch by a Table's **Id** primary key field. + + var track = dbCmd.QueryById(1); + + +# Limitations + +For simplicity, and to be able to have the same POCO class persisted in db4o, memcached, redis or on the file system (i.e. providers included in ServiceStack), each model must have an '`Id`' property which is its primary key. + + +# More Examples + +In its simplest useage, OrmLite can persist any POCO type without any attributes required: + + public class SimpleExample + { + public int Id { get; set; } + public string Name { get; set; } + } + + //Set once before use (i.e. in a static constructor). + OrmLiteConfig.DialectProvider = new SqliteOrmLiteDialectProvider(); + + using (IDbConnection db = "/path/to/db.sqlite".OpenDbConnection()) + using (IDbCommand dbConn = db.CreateCommand()) + { + dbConn.CreateTable(true); + dbConn.Insert(new SimpleExample { Id=1, Name="Hello, World!"}); + var rows = dbConn.Select(); + + Assert.That(rows, Has.Count(1)); + Assert.That(rows[0].Id, Is.EqualTo(1)); + } + +To get a better idea of the features of OrmLite lets walk through a complete example using sample tables from the Northwind database. +_ (Full source code for this example is [available here](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/ShippersExample.cs).) _ + +So with no other configuration using only the classes below: + + [Alias("Shippers")] + public class Shipper + : IHasId + { + [AutoIncrement] + [Alias("ShipperID")] + public int Id { get; set; } + + [Required] + [Index(Unique = true)] + [StringLength(40)] + public string CompanyName { get; set; } + + [StringLength(24)] + public string Phone { get; set; } + + [References(typeof(ShipperType))] + public int ShipperTypeId { get; set; } + } + + [Alias("ShipperTypes")] + public class ShipperType + : IHasId + { + [AutoIncrement] + [Alias("ShipperTypeID")] + public int Id { get; set; } + + [Required] + [Index(Unique = true)] + [StringLength(40)] + public string Name { get; set; } + } + + public class SubsetOfShipper + { + public int ShipperId { get; set; } + public string CompanyName { get; set; } + } + + public class ShipperTypeCount + { + public int ShipperTypeId { get; set; } + public int Total { get; set; } + } + + +### Creating tables +Creating tables is a simple 1-liner: + + using (IDbConnection dbConn = ":memory:".OpenDbConnection()) + using (IDbCommand dbCmd = dbConn.CreateCommand()) + { + const bool overwrite = false; + dbCmd.CreateTables(overwrite, typeof(Shipper), typeof(ShipperType)); + } + + /* In debug mode the line above prints: + DEBUG: CREATE TABLE "Shippers" + ( + "ShipperID" INTEGER PRIMARY KEY AUTOINCREMENT, + "CompanyName" VARCHAR(40) NOT NULL, + "Phone" VARCHAR(24) NULL, + "ShipperTypeId" INTEGER NOT NULL, + + CONSTRAINT "FK_Shippers_ShipperTypes" FOREIGN KEY ("ShipperTypeId") REFERENCES "ShipperTypes" ("ShipperID") + ); + DEBUG: CREATE UNIQUE INDEX uidx_shippers_companyname ON "Shippers" ("CompanyName" ASC); + DEBUG: CREATE TABLE "ShipperTypes" + ( + "ShipperTypeID" INTEGER PRIMARY KEY AUTOINCREMENT, + "Name" VARCHAR(40) NOT NULL + ); + DEBUG: CREATE UNIQUE INDEX uidx_shippertypes_name ON "ShipperTypes" ("Name" ASC); + */ + + +### Transaction Support +As we have direct access to IDbCommand and friends - playing with transactions is easy: + + int trainsTypeId, planesTypeId; + using (IDbTransaction dbTrans = dbCmd.BeginTransaction()) + { + dbCmd.Insert(new ShipperType { Name = "Trains" }); + trainsTypeId = (int) dbCmd.GetLastInsertId(); + + dbCmd.Insert(new ShipperType { Name = "Planes" }); + planesTypeId = (int) dbCmd.GetLastInsertId(); + + dbTrans.Commit(); + } + using (IDbTransaction dbTrans = dbCmd.BeginTransaction(IsolationLevel.ReadCommitted)) + { + dbCmd.Insert(new ShipperType { Name = "Automobiles" }); + Assert.That(dbCmd.Select(), Has.Count(3)); + + dbTrans.Rollback(); + } + Assert.That(dbCmd.Select(), Has.Count(2)); + + +### CRUD Operations +No ORM is complete without the standard crud operations: + + //Performing standard Insert's and Selects + dbCmd.Insert(new Shipper { CompanyName = "Trains R Us", Phone = "555-TRAINS", ShipperTypeId = trainsTypeId }); + dbCmd.Insert(new Shipper { CompanyName = "Planes R Us", Phone = "555-PLANES", ShipperTypeId = planesTypeId }); + dbCmd.Insert(new Shipper { CompanyName = "We do everything!", Phone = "555-UNICORNS", ShipperTypeId = planesTypeId }); + + var trainsAreUs = dbCmd.First("ShipperTypeId = {0}", trainsTypeId); + Assert.That(trainsAreUs.CompanyName, Is.EqualTo("Trains R Us")); + Assert.That(dbCmd.Select("CompanyName = {0} OR Phone = {1}", "Trains R Us", "555-UNICORNS"), Has.Count(2)); + Assert.That(dbCmd.Select("ShipperTypeId = {0}", planesTypeId), Has.Count(2)); + + //Lets update a record + trainsAreUs.Phone = "666-TRAINS"; + dbCmd.Update(trainsAreUs); + Assert.That(dbCmd.GetById(trainsAreUs.Id).Phone, Is.EqualTo("666-TRAINS")); + + //Then make it disappear + dbCmd.Delete(trainsAreUs); + Assert.That(dbCmd.GetByIdOrDefault(trainsAreUs.Id), Is.Null); + + //And bring it back again + dbCmd.Insert(trainsAreUs); + + +### Performing custom queries +And with access to raw sql when you need it - the database is your oyster :) + + //Select only a subset from the table + var partialColumns = dbCmd.Select(typeof (Shipper), "ShipperTypeId = {0}", planesTypeId); + Assert.That(partialColumns, Has.Count(2)); + + //Select into another POCO class that matches the sql results + var rows = dbCmd.Select( + "SELECT ShipperTypeId, COUNT(*) AS Total FROM Shippers GROUP BY ShipperTypeId ORDER BY COUNT(*)"); + + Assert.That(rows, Has.Count(2)); + Assert.That(rows[0].ShipperTypeId, Is.EqualTo(trainsTypeId)); + Assert.That(rows[0].Total, Is.EqualTo(1)); + Assert.That(rows[1].ShipperTypeId, Is.EqualTo(planesTypeId)); + Assert.That(rows[1].Total, Is.EqualTo(2)); + + + //And finally lets quickly clean up the mess we've made: + dbCmd.DeleteAll(); + dbCmd.DeleteAll(); + + Assert.That(dbCmd.Select(), Has.Count(0)); + Assert.That(dbCmd.Select(), Has.Count(0)); \ No newline at end of file diff --git a/src/Docs/packages.config b/src/Docs/packages.config new file mode 100644 index 00000000..6b7d575f --- /dev/null +++ b/src/Docs/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Docs/packages/ServiceStack.4.0.11/ServiceStack.4.0.11.nupkg b/src/Docs/packages/ServiceStack.4.0.11/ServiceStack.4.0.11.nupkg new file mode 100644 index 00000000..4ec38fea Binary files /dev/null and b/src/Docs/packages/ServiceStack.4.0.11/ServiceStack.4.0.11.nupkg differ diff --git a/src/Docs/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.dll b/src/Docs/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.dll new file mode 100644 index 00000000..83933d41 Binary files /dev/null and b/src/Docs/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.dll differ diff --git a/src/Docs/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.xml b/src/Docs/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.xml new file mode 100644 index 00000000..d238a55a --- /dev/null +++ b/src/Docs/packages/ServiceStack.4.0.11/lib/net40/ServiceStack.xml @@ -0,0 +1,8174 @@ + + + + ServiceStack + + + + + Base class to create request filter attributes only for specific HTTP methods (GET, POST...) + + + + + Creates a new + + Defines when the filter should be executed + + + + This method is only executed if the HTTP method matches the property. + + The http request wrapper + The http response wrapper + The request DTO + + + + Create a ShallowCopy of this instance. + + + + + + Inherit from this class if you want to host your web services inside a + Console Application, Windows Service, etc. + + Usage of HttpListener allows you to host webservices on the same port (:80) as IIS + however it requires admin user privillages. + + + + + Wrapper class for the HTTPListener to allow easier access to the + server, for start and stop management and event routing of the actual + inbound requests. + + + + + ASP.NET or HttpListener ServiceStack host + + + + + Register dependency in AppHost IOC on Startup + + + + + AutoWired Registration of an interface with a concrete type in AppHost IOC on Startup. + + + + + Allows the clean up for executed autowired services and filters. + Calls directly after services and filters are executed. + + + + + Called at the end of each request. Enables Request Scope. + + + + + Register an Adhoc web service on Startup + + + + + Apply plugins to this AppHost + + + + + Create a service runner for IService actions + + + + + Resolve the absolute url for this request + + + + + Resolve localized text, returns itself by default. + + + + + Register user-defined custom routes. + + + + + Register custom ContentType serializers + + + + + Add Request Filters, to be applied before the dto is deserialized + + + + + Add Request Filters for HTTP Requests + + + + + Add Response Filters for HTTP Responses + + + + + Add Request Filters for MQ/TCP Requests + + + + + Add Response Filters for MQ/TCP Responses + + + + + Add alternative HTML View Engines + + + + + Provide an exception handler for unhandled exceptions + + + + + Provide an exception handler for un-caught exceptions + + + + + Skip the ServiceStack Request Pipeline and process the returned IHttpHandler instead + + + + + Provide a catch-all handler that doesn't match any routes + + + + + Use a Custom Error Handler for handling specific error HttpStatusCodes + + + + + Provide a custom model minder for a specific Request DTO + + + + + The AppHost config + + + + + List of pre-registered and user-defined plugins to be enabled in this AppHost + + + + + Virtual access to file resources + + + + + Funqlets are a set of components provided as a package + to an existing container (like a module). + + + + + Configure the given container with the + registrations provided by the funqlet. + + Container to register. + + + + Executed immediately before a Service is executed. Use return to change the request DTO used, must be of the same type. + + + + + Executed immediately after a service is executed. Use return to change response used. + + + + + Occurs when the Service throws an Exception. + + + + + Occurs when an exception is thrown whilst processing a request. + + + + + Apply PreRequest Filters for participating Custom Handlers, e.g. RazorFormat, MarkdownFormat, etc + + + + + Applies the raw request filters. Returns whether or not the request has been handled + and no more processing should be done. + + + + + + Applies the request filters. Returns whether or not the request has been handled + and no more processing should be done. + + + + + + Applies the response filters. Returns whether or not the request has been handled + and no more processing should be done. + + + + + + The AppHost.Container. Note: it is not thread safe to register dependencies after AppStart. + + + + + Starts the Web Service + + + A Uri that acts as the base that the server is listening on. + Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/ + Note: the trailing slash is required! For more info see the + HttpListener.Prefixes property on MSDN. + + + + + Shut down the Web Service + + + + + Overridable method that can be used to implement a custom hnandler + + + + + + Reserves the specified URL for non-administrator users and accounts. + http://msdn.microsoft.com/en-us/library/windows/desktop/cc307223(v=vs.85).aspx + + Reserved Url if the process completes successfully + + + + Creates the required missing tables or DB schema + + + + + Redirect to the https:// version of this url if not already. + + + + + Don't redirect when in DebugMode + + + + + Don't redirect if the request was a forwarded request, e.g. from a Load Balancer + + + + + Single threaded message handler that can process all messages + of a particular message type. + + + + + Process all messages pending + + + + + + Process messages from a single queue. + + + The queue to process + A predicate on whether to continue processing the next message if any + + + + + Process a single message + + + + + Get Current Stats for this Message Handler + + + + + + The type of the message this handler processes + + + + + Encapsulates creating a new message handler + + + + + Processes all messages in a Normal and Priority Queue. + Expects to be called in 1 thread. i.e. Non Thread-Safe. + + + + + + A convenient repository base class you can inherit from to reduce the boilerplate + with accessing a managed IDbConnection + + + + + A convenient base class for your injected service dependencies that reduces the boilerplate + with managed access to ServiceStack's built-in providers + + + + + This class stores the caller call context in order to restore + it when the work item is executed in the thread pool environment. + + + + + Constructor + + + + + Captures the current thread context + + + + + + Applies the thread context stored earlier + + + + + + EventWaitHandleFactory class. + This is a static class that creates AutoResetEvent and ManualResetEvent objects. + In WindowCE the WaitForMultipleObjects API fails to use the Handle property + of XxxResetEvent. It can use only handles that were created by the CreateEvent API. + Consequently this class creates the needed XxxResetEvent and replaces the handle if + it's a WindowsCE OS. + + + + + Create a new AutoResetEvent object + + Return a new AutoResetEvent object + + + + Create a new ManualResetEvent object + + Return a new ManualResetEvent object + + + + Represents an exception in case IWorkItemResult.GetResult has been canceled + + + Represents an exception in case IWorkItemResult.GetResult has been canceled + + + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + Represents an exception in case IWorkItemResult.GetResult has been timed out + + + + + A delegate that represents the method to run as the work item + + A state object for the method to run + + + + A delegate to call after the WorkItemCallback completed + + The work item result object + + + + A delegate to call after the WorkItemCallback completed + + The work item result object + + + + A delegate to call when a WorkItemsGroup becomes idle + + A reference to the WorkItemsGroup that became idle + + + + A delegate to call after a thread is created, but before + it's first use. + + + + + A delegate to call when a thread is about to exit, after + it is no longer belong to the pool. + + + + + Defines the availeable priorities of a work item. + The higher the priority a work item has, the sooner + it will be executed. + + + + + IWorkItemsGroup interface + Created by SmartThreadPool.CreateWorkItemsGroup() + + + + + Get an array with all the state objects of the currently running items. + The array represents a snap shot and impact performance. + + + + + Starts to execute work items + + + + + Cancel all the work items. + Same as Cancel(false) + + + + + Cancel all work items using thread abortion + + True to stop work items by raising ThreadAbortException + + + + Wait for all work item to complete. + + + + + Wait for all work item to complete, until timeout expired + + How long to wait for the work items to complete + Returns true if work items completed within the timeout, otherwise false. + + + + Wait for all work item to complete, until timeout expired + + How long to wait for the work items to complete in milliseconds + Returns true if work items completed within the timeout, otherwise false. + + + + Queue a work item + + A callback to execute + Returns a work item result + + + + Queue a work item + + A callback to execute + The priority of the work item + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + The work item priority + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + The work item priority + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + The work item priority + Returns a work item result + + + + Queue a work item + + Work item info + A callback to execute + Returns a work item result + + + + Queue a work item + + Work item information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult object, but its GetResult() will always return null + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Queue a work item. + + Returns a IWorkItemResult<TResult> object. + its GetResult() returns a TResult object + + + + Get/Set the name of the WorkItemsGroup + + + + + Get/Set the maximum number of workitem that execute cocurrency on the thread pool + + + + + Get the number of work items waiting in the queue. + + + + + Get the WorkItemsGroup start information + + + + + IsIdle is true when there are no work items running or queued. + + + + + This event is fired when all work items are completed. + (When IsIdle changes to true) + This event only work on WorkItemsGroup. On SmartThreadPool + it throws the NotImplementedException. + + + + + Never call to the PostExecute call back + + + + + Call to the PostExecute only when the work item is cancelled + + + + + Call to the PostExecute only when the work item is not cancelled + + + + + Always call to the PostExecute + + + + + The common interface of IWorkItemResult and IWorkItemResult<T> + + + + + This method intent is for internal use. + + + + + + This method intent is for internal use. + + + + + + IWorkItemResult interface. + Created when a WorkItemCallback work item is queued. + + + + + IWorkItemResult<TResult> interface. + Created when a Func<TResult> work item is queued. + + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits. + + The result of the work item + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + Timeout in milliseconds, or -1 for infinite + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the blocking if needed + The result of the work item + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + The result of the work item + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits. + + Filled with the exception if one was thrown + The result of the work item + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + + + Filled with the exception if one was thrown + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout. + + + Filled with the exception if one was thrown + + The result of the work item + On timeout throws WorkItemTimeoutException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + Timeout in milliseconds, or -1 for infinite + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the blocking if needed + Filled with the exception if one was thrown + The result of the work item + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. + + The result of the work item + + Filled with the exception if one was thrown + + + On timeout throws WorkItemTimeoutException + On cancel throws WorkItemCancelException + + + + Same as Cancel(false). + + + + + Cancel the work item execution. + If the work item is in the queue then it won't execute + If the work item is completed, it will remain completed + If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled + property to check if the work item has been cancelled. If the abortExecution is set to true then + the Smart Thread Pool will send an AbortException to the running thread to stop the execution + of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException. + If the work item is already cancelled it will remain cancelled + + When true send an AbortException to the executing thread. + Returns true if the work item was not completed, otherwise false. + + + + Gets an indication whether the asynchronous operation has completed. + + + + + Gets an indication whether the asynchronous operation has been canceled. + + + + + Gets the user-defined object that contains context data + for the work item method. + + + + + Get the work item's priority + + + + + Return the result, same as GetResult() + + + + + Returns the exception if occured otherwise returns null. + + + + + An internal delegate to call when the WorkItem starts or completes + + + + + This method is intent for internal use. + + + + + PriorityQueue class + This class is not thread safe because we use external lock + + + + + The number of queues, there is one for each type of priority + + + + + Work items queues. There is one for each type of priority + + + + + The total number of work items within the queues + + + + + Use with IEnumerable interface + + + + + Enqueue a work item. + + A work item + + + + Dequeque a work item. + + Returns the next work item + + + + Find the next non empty queue starting at queue queueIndex+1 + + The index-1 to start from + + The index of the next non empty queue or -1 if all the queues are empty + + + + + Clear all the work items + + + + + Returns an enumerator to iterate over the work items + + Returns an enumerator + + + + The number of work items + + + + + The class the implements the enumerator + + + + + Smart thread pool class. + + + + + Contains the name of this instance of SmartThreadPool. + Can be changed by the user. + + + + + Cancel all the work items. + Same as Cancel(false) + + + + + Wait for the SmartThreadPool/WorkItemsGroup to be idle + + + + + Wait for the SmartThreadPool/WorkItemsGroup to be idle + + + + + Queue a work item + + A callback to execute + Returns a work item result + + + + Queue a work item + + A callback to execute + The priority of the work item + Returns a work item result + + + + Queue a work item + + Work item info + A callback to execute + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + The work item priority + Returns a work item result + + + + Queue a work item + + Work item information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + The work item priority + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + Returns a work item result + + + + Queue a work item + + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + The work item priority + Returns a work item result + + + + Get/Set the name of the SmartThreadPool/WorkItemsGroup instance + + + + + IsIdle is true when there are no work items running or queued. + + + + + Default minimum number of threads the thread pool contains. (0) + + + + + Default maximum number of threads the thread pool contains. (25) + + + + + Default idle timeout in milliseconds. (One minute) + + + + + Indicate to copy the security context of the caller and then use it in the call. (false) + + + + + Indicate to copy the HTTP context of the caller and then use it in the call. (false) + + + + + Indicate to dispose of the state objects if they support the IDispose interface. (false) + + + + + The default option to run the post execute (CallToPostExecute.Always) + + + + + The default work item priority (WorkItemPriority.Normal) + + + + + The default is to work on work items as soon as they arrive + and not to wait for the start. (false) + + + + + The default thread priority (ThreadPriority.Normal) + + + + + The default thread pool name. (SmartThreadPool) + + + + + The default fill state with params. (false) + It is relevant only to QueueWorkItem of Action<...>/Func<...> + + + + + The default thread backgroundness. (true) + + + + + The default apartment state of a thread in the thread pool. + The default is ApartmentState.Unknown which means the STP will not + set the apartment of the thread. It will use the .NET default. + + + + + The default post execute method to run. (None) + When null it means not to call it. + + + + + The default name to use for the performance counters instance. (null) + + + + + The default Max Stack Size. (SmartThreadPool) + + + + + Dictionary of all the threads in the thread pool. + + + + + Queue of work items. + + + + + Count the work items handled. + Used by the performance counter. + + + + + Number of threads that currently work (not idle). + + + + + Stores a copy of the original STPStartInfo. + It is used to change the MinThread and MaxThreads + + + + + Total number of work items that are stored in the work items queue + plus the work items that the threads in the pool are working on. + + + + + Signaled when the thread pool is idle, i.e. no thread is busy + and the work items queue is empty + + + + + An event to signal all the threads to quit immediately. + + + + + A flag to indicate if the Smart Thread Pool is now suspended. + + + + + A flag to indicate the threads to quit. + + + + + Counts the threads created in the pool. + It is used to name the threads. + + + + + Indicate that the SmartThreadPool has been disposed + + + + + Holds all the WorkItemsGroup instaces that have at least one + work item int the SmartThreadPool + This variable is used in case of Shutdown + + + + + A common object for all the work items int the STP + so we can mark them to cancel in O(1) + + + + + Windows STP performance counters + + + + + Local STP performance counters + + + + + Constructor + + + + + Constructor + + Idle timeout in milliseconds + + + + Constructor + + Idle timeout in milliseconds + Upper limit of threads in the pool + + + + Constructor + + Idle timeout in milliseconds + Upper limit of threads in the pool + Lower limit of threads in the pool + + + + Constructor + + A SmartThreadPool configuration that overrides the default behavior + + + + Waits on the queue for a work item, shutdown, or timeout. + + + Returns the WaitingCallback or null in case of timeout or shutdown. + + + + + Put a new work item in the queue + + A work item to queue + + + + Inform that the current thread is about to quit or quiting. + The same thread may call this method more than once. + + + + + Starts new threads + + The number of threads to start + + + + A worker thread method that processes work items from the work items queue. + + + + + Force the SmartThreadPool to shutdown + + + + + Force the SmartThreadPool to shutdown with timeout + + + + + Empties the queue of work items and abort the threads in the pool. + + + + + Wait for all work items to complete + + Array of work item result objects + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + true when every work item in workItemResults has completed; otherwise false. + + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + true when every work item in workItemResults has completed; otherwise false. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + + The array index of the work item result that satisfied the wait, or WaitTimeout if any of the work items has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Creates a new WorkItemsGroup. + + The number of work items that can be run concurrently + A reference to the WorkItemsGroup + + + + Creates a new WorkItemsGroup. + + The number of work items that can be run concurrently + A WorkItemsGroup configuration that overrides the default behavior + A reference to the WorkItemsGroup + + + + Checks if the work item has been cancelled, and if yes then abort the thread. + Can be used with Cancel and timeout + + + + + Get an array with all the state objects of the currently running items. + The array represents a snap shot and impact performance. + + + + + Start the thread pool if it was started suspended. + If it is already running, this method is ignored. + + + + + Cancel all work items using thread abortion + + True to stop work items by raising ThreadAbortException + + + + Wait for the thread pool to be idle + + + + + Executes all actions in parallel. + Returns when they all finish. + + Actions to execute + + + + Executes all actions in parallel. + Returns when they all finish. + + Actions to execute + + + + Executes all actions in parallel + Returns when the first one completes + + Actions to execute + + + + Executes all actions in parallel + Returns when the first one completes + + Actions to execute + + + + Executes actions in sequence asynchronously. + Returns immediately. + + A state context that passes + Actions to execute in the order they should run + + + + Executes actions in sequence asynchronously. + Returns immediately. + + + Actions to execute in the order they should run + + + + An event to call after a thread is created, but before + it's first use. + + + + + An event to call when a thread is about to exit, after + it is no longer belong to the pool. + + + + + A reference to the current work item a thread from the thread pool + is executing. + + + + + This event is fired when a thread is created. + Use it to initialize a thread before the work items use it. + + + + + This event is fired when a thread is terminating. + Use it for cleanup. + + + + + Get/Set the lower limit of threads in the pool. + + + + + Get/Set the upper limit of threads in the pool. + + + + + Get the number of threads in the thread pool. + Should be between the lower and the upper limits. + + + + + Get the number of busy (not idle) threads in the thread pool. + + + + + Returns true if the current running work item has been cancelled. + Must be used within the work item's callback method. + The work item should sample this value in order to know if it + needs to quit before its completion. + + + + + Thread Pool start information (readonly) + + + + + Return the local calculated performance counters + Available only if STPStartInfo.EnableLocalPerformanceCounters is true. + + + + + Get/Set the maximum number of work items that execute cocurrency on the thread pool + + + + + Get the number of work items in the queue. + + + + + WorkItemsGroup start information (readonly) + + + + + This event is fired when all work items are completed. + (When IsIdle changes to true) + This event only work on WorkItemsGroup. On SmartThreadPool + it throws the NotImplementedException. + + + + + The thread creation time + The value is stored as UTC value. + + + + + The last time this thread has been running + It is updated by IAmAlive() method + The value is stored as UTC value. + + + + + A reference from each thread in the thread pool to its SmartThreadPool + object container. + With this variable a thread can know whatever it belongs to a + SmartThreadPool. + + + + + A reference to the current work item a thread from the thread pool + is executing. + + + + + Summary description for STPPerformanceCounter. + + + + + Summary description for STPStartInfo. + + + + + Summary description for WIGStartInfo. + + + + + Get a readonly version of this WIGStartInfo + + Returns a readonly reference to this WIGStartInfoRO + + + + Get/Set if to use the caller's security context + + + + + Get/Set if to use the caller's HTTP context + + + + + Get/Set if to dispose of the state object of a work item + + + + + Get/Set the run the post execute options + + + + + Get/Set the default post execute callback + + + + + Get/Set if the work items execution should be suspended until the Start() + method is called. + + + + + Get/Set the default priority that a work item gets when it is enqueued + + + + + Get/Set the if QueueWorkItem of Action<...>/Func<...> fill the + arguments as an object array into the state of the work item. + The arguments can be access later by IWorkItemResult.State. + + + + + Get a readonly version of this STPStartInfo. + + Returns a readonly reference to this STPStartInfo + + + + Get/Set the idle timeout in milliseconds. + If a thread is idle (starved) longer than IdleTimeout then it may quit. + + + + + Get/Set the lower limit of threads in the pool. + + + + + Get/Set the upper limit of threads in the pool. + + + + + Get/Set the scheduling priority of the threads in the pool. + The Os handles the scheduling. + + + + + Get/Set the thread pool name. Threads will get names depending on this. + + + + + Get/Set the performance counter instance name of this SmartThreadPool + The default is null which indicate not to use performance counters at all. + + + + + Enable/Disable the local performance counter. + This enables the user to get some performance information about the SmartThreadPool + without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.) + The default is false. + + + + + Get/Set backgroundness of thread in thread pool. + + + + + Get/Set the apartment state of threads in the thread pool + + + + + Get/Set the max stack size of threads in the thread pool + + + + + Holds a callback delegate and the state for that delegate. + + + + + Callback delegate for the callback. + + + + + State with which to call the callback delegate. + + + + + Stores the caller's context + + + + + Holds the result of the mehtod + + + + + Hold the exception if the method threw it + + + + + Hold the state of the work item + + + + + A ManualResetEvent to indicate that the result is ready + + + + + A reference count to the _workItemCompleted. + When it reaches to zero _workItemCompleted is Closed + + + + + Represents the result state of the work item + + + + + Work item info + + + + + A reference to an object that indicates whatever the + WorkItemsGroup has been canceled + + + + + A reference to an object that indicates whatever the + SmartThreadPool has been canceled + + + + + The work item group this work item belong to. + + + + + The thread that executes this workitem. + This field is available for the period when the work item is executed, before and after it is null. + + + + + The absulote time when the work item will be timeout + + + + + Stores how long the work item waited on the stp queue + + + + + Stores how much time it took the work item to execute after it went out of the queue + + + + + Initialize the callback holding object. + + The workItemGroup of the workitem + The WorkItemInfo of te workitem + Callback delegate for the callback. + State with which to call the callback delegate. + + We assume that the WorkItem object is created within the thread + that meant to run the callback + + + + Change the state of the work item to in progress if it wasn't canceled. + + + Return true on success or false in case the work item was canceled. + If the work item needs to run a post execute then the method will return true. + + + + + Execute the work item and the post execute + + + + + Execute the work item + + + + + Runs the post execute callback + + + + + Set the result of the work item to return + + The result of the work item + The exception that was throw while the workitem executed, null + if there was no exception. + + + + Returns the work item result + + The work item result + + + + Wait for all work items to complete + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + true when every work item in waitableResults has completed; otherwise false. + + + + + Waits for any of the work items in the specified array to complete, cancel, or timeout + + Array of work item result objects + The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. + + true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. + + A cancel wait handle to interrupt the wait if needed + + The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. + + + + + Fill an array of wait handles with the work items wait handles. + + An array of work item results + An array of wait handles to fill + + + + Release the work items' wait handles + + An array of work item results + + + + Sets the work item's state + + The state to set the work item to + + + + Signals that work item has been completed or canceled + + Indicates that the work item has been canceled + + + + Cancel the work item if it didn't start running yet. + + Returns true on success or false if the work item is in progress or already completed + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits for the result, timeout, or cancel. + In case of error the method throws and exception + + The result of the work item + + + + Get the result of the work item. + If the work item didn't run yet then the caller waits for the result, timeout, or cancel. + In case of error the e argument is filled with the exception + + The result of the work item + + + + A wait handle to wait for completion, cancel, or timeout + + + + + Called when the WorkItem starts + + + + + Called when the WorkItem completes + + + + + Returns true when the work item has completed or canceled + + + + + Returns true when the work item has canceled + + + + + Returns the priority of the work item + + + + + Indicates the state of the work item in the thread pool + + + + + A back reference to the work item + + + + + Return the result, same as GetResult() + + + + + Returns the exception if occured otherwise returns null. + This value is valid only after the work item completed, + before that it is always null. + + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + A callback to execute + Returns a work item + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + A callback to execute + The priority of the work item + Returns a work item + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + Work item info + A callback to execute + Returns a work item + + + + Create a new work item + + The WorkItemsGroup of this workitem + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + The work item priority + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + Work item information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + The work item priority + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + Returns a work item + + + + Create a new work item + + The work items group + Work item group start information + A callback to execute + + The context object of the work item. Used for passing arguments to the work item. + + + A delegate to call after the callback completion + + Indicates on which cases to call to the post execute callback + The work item priority + Returns a work item + + + + Summary description for WorkItemInfo. + + + + + Get/Set if to use the caller's security context + + + + + Get/Set if to use the caller's HTTP context + + + + + Get/Set if to dispose of the state object of a work item + + + + + Get/Set the run the post execute options + + + + + Get/Set the post execute callback + + + + + Get/Set the work item's priority + + + + + Get/Set the work item's timout in milliseconds. + This is a passive timout. When the timout expires the work item won't be actively aborted! + + + + + Summary description for WorkItemsGroup. + + + + + A reference to the SmartThreadPool instance that created this + WorkItemsGroup. + + + + + A flag to indicate if the Work Items Group is now suspended. + + + + + Defines how many work items of this WorkItemsGroup can run at once. + + + + + Priority queue to hold work items before they are passed + to the SmartThreadPool. + + + + + Indicate how many work items are waiting in the SmartThreadPool + queue. + This value is used to apply the concurrency. + + + + + Indicate how many work items are currently running in the SmartThreadPool. + This value is used with the Cancel, to calculate if we can send new + work items to the STP. + + + + + WorkItemsGroup start information + + + + + Signaled when all of the WorkItemsGroup's work item completed. + + + + + A common object for all the work items that this work items group + generate so we can mark them to cancel in O(1) + + + + + Start the Work Items Group if it was started suspended + + + + + Wait for the thread pool to be idle + + + + + The OnIdle event + + + + + WorkItemsGroup start information + + + + + WorkItemsQueue class. + + + + + Waiters queue (implemented as stack). + + + + + Waiters count + + + + + Work items queue + + + + + Indicate that work items are allowed to be queued + + + + + A flag that indicates if the WorkItemsQueue has been disposed. + + + + + Enqueue a work item to the queue. + + + + + Waits for a work item or exits on timeout or cancel + + Timeout in milliseconds + Cancel wait handle + Returns true if the resource was granted + + + + Cleanup the work items queue, hence no more work + items are allowed to be queue + + + + + Returns the WaiterEntry of the current thread + + + In order to avoid creation and destuction of WaiterEntry + objects each thread has its own WaiterEntry object. + + + + Push a new waiter into the waiter's stack + + A waiter to put in the stack + + + + Pop a waiter from the waiter's stack + + Returns the first waiter in the stack + + + + Remove a waiter from the stack + + A waiter entry to remove + If true the waiter count is always decremented + + + + Each thread in the thread pool keeps its own waiter entry. + + + + + Returns the current number of work items in the queue + + + + + Returns the current number of waiters + + + + + Event to signal the waiter that it got the work item. + + + + + Flag to know if this waiter already quited from the queue + because of a timeout. + + + + + Flag to know if the waiter was signaled and got a work item. + + + + + A work item that passed directly to the waiter withou going + through the queue + + + + + Signal the waiter that it got a work item. + + Return true on success + The method fails if Timeout() preceded its call + + + + Mark the wait entry that it has been timed out + + Return true on success + The method fails if Signal() preceded its call + + + + Reset the wait entry so it can be used again + + + + + Free resources + + + + + Respond with a 'Soft redirect' so smart clients (e.g. ajax) have access to the response and + can decide whether or not they should redirect + + + + + Decorate the response with an additional client-side event to instruct participating + smart clients (e.g. ajax) with hints to transparently invoke client-side functionality + + + + + Shortcut to get the ResponseDTO whether it's bare or inside a IHttpResult + + + + + + + Alias of AsDto + + + + + Shortcut to get the ResponseDTO whether it's bare or inside a IHttpResult + + + TResponse if found; otherwise null + + + + Alias of AsDto + + + + + Whether the response is an IHttpError or Exception + + + + + rangeHeader should be of the format "bytes=0-" or "bytes=0-12345" or "bytes=123-456" + + + + + Adds 206 PartialContent Status, Content-Range and Content-Length headers + + + + + Writes partial range as specified by start-end, from fromStream to toStream. + + + + + Service error logs are kept in 'urn:ServiceErrors:{ServiceName}' + + + + + Combined service error logs are maintained in 'urn:ServiceErrors:All' + + + + + RequestLogs service Route, default is /requestlogs + + + + + Turn On/Off Session Tracking + + + + + Turn On/Off Logging of Raw Request Body, default is Off + + + + + Turn On/Off Tracking of Responses + + + + + Turn On/Off Tracking of Exceptions + + + + + Size of InMemoryRollingRequestLogger circular buffer + + + + + Limit access to /requestlogs service to these roles + + + + + Change the RequestLogger provider. Default is InMemoryRollingRequestLogger + + + + + Don't log requests of these types. By default RequestLog's are excluded + + + + + Don't log request bodys for services with sensitive information. + By default Auth and Registration requests are hidden. + + + + + Generic + Useful IService base class + + + + + Resolve an alternate Web Service from ServiceStack's IOC container. + + + + + + + Dynamic Session Bag + + + + + Typed UserSession + + + + + Indicates that the request dto, which is associated with this attribute, + requires authentication. + + + + + Restrict authentication to a specific . + For example, if this attribute should only permit access + if the user is authenticated with , + you should set this property to . + + + + + Redirect the client to a specific URL if authentication failed. + If this property is null, simply `401 Unauthorized` is returned. + + + + + Enable the authentication feature and configure the AuthService. + + + + + Inject logic into existing services by introspecting the request and injecting your own + validation logic. Exceptions thrown will have the same behaviour as if the service threw it. + + If a non-null object is returned the request will short-circuit and return that response. + + The instance of the service + GET,POST,PUT,DELETE + + Response DTO; non-null will short-circuit execution and return that response + + + + Public API entry point to authenticate via code + + + null; if already autenticated otherwise a populated instance of AuthResponse + + + + The specified may change as a side-effect of this method. If + subsequent code relies on current data be sure to reload + the session istance via . + + + + + Remove the Users Session + + + + + + + + The entry point for all AuthProvider providers. Runs inside the AuthService so exceptions are treated normally. + Overridable so you can provide your own Auth implementation. + + + + + Determine if the current session is already authenticated with this AuthProvider + + + + + Allows specifying a global fallback config that if exists is formatted with the Provider as the first arg. + E.g. this appSetting with the TwitterAuthProvider: + oauth.CallbackUrl="http://localhost:11001/auth/{0}" + Would result in: + oauth.CallbackUrl="http://localhost:11001/auth/twitter" + + + + + + Remove the Users Session + + + + + + + + Saves the Auth Tokens for this request. Called in OnAuthenticated(). + Overrideable, the default behaviour is to call IUserAuthRepository.CreateOrMergeAuthSession(). + + + + + Base class for entity validator classes. + + The type of the object being validated + + + + Defines a validator for a particualr type. + + + + + + Defines a validator for a particular type. + + + + + Validates the specified instance + + + A ValidationResult containing any validation failures + + + + Validates the specified instance. + + A ValidationContext + A ValidationResult object containy any validation failures. + + + + Creates a hook to access various meta data properties + + A IValidatorDescriptor object which contains methods to access metadata + + + + Checks to see whether the validator can validate objects of the specified type + + + + + Validates the specified instance. + + The instance to validate + A ValidationResult object containing any validation failures. + + + + Sets the cascade mode for all rules within this validator. + + + + + Validates the specified instance + + The object to validate + A ValidationResult object containing any validation failures + + + + Validates the specified instance. + + Validation Context + A ValidationResult object containing any validation failures. + + + + Adds a rule to the current validator. + + + + + + Creates a that can be used to obtain metadata about the current validator. + + + + + Defines a validation rule for a specify property. + + + RuleFor(x => x.Surname)... + + The type of property being validated + The expression representing the property to validate + an IRuleBuilder instance on which validators can be defined + + + + Defines a custom validation rule using a lambda expression. + If the validation rule fails, it should return a instance of a ValidationFailure + If the validation rule succeeds, it should return null. + + A lambda that executes custom validation rules. + + + + Defines a custom validation rule using a lambda expression. + If the validation rule fails, it should return an instance of ValidationFailure + If the validation rule succeeds, it should return null. + + A lambda that executes custom validation rules + + + + Defines a RuleSet that can be used to group together several validators. + + The name of the ruleset. + Action that encapsulates the rules in the ruleset. + + + + Defines a RuleSet that can be used to provide specific validation rules for specific HTTP methods (GET, POST...) + + The HTTP methods where this rule set should be used. + Action that encapuslates the rules in the ruleset. + + + + Defines a condition that applies to several rules + + The condition that should apply to multiple rules + Action that encapsulates the rules. + + + + + Defiles an inverse condition that applies to several rules + + The condition that should be applied to multiple rules + Action that encapsulates the rules + + + + Returns an enumerator that iterates through the collection of validation rules. + + + A that can be used to iterate through the collection. + + 1 + + + + Sets the cascade mode for all rules within this validator. + + + + + Create a Facebook App at: https://developers.facebook.com/apps + The Callback URL for your app should match the CallbackUrl provided. + + + + + The entry point for all AuthProvider providers. Runs inside the AuthService so exceptions are treated normally. + Overridable so you can provide your own Auth implementation. + + + + + + + + + Sets the CallbackUrl and session.ReferrerUrl if not set and initializes the session tokens for this AuthProvider + + + + + + + + + Download Yammer User Info given its ID. + + + The Yammer User ID. + + + The User info in JSON format. + + + + Yammer provides a method to retrieve current user information via + "https://www.yammer.com/api/v1/users/current.json". + + + However, to ensure consistency with the rest of the Auth codebase, + the explicit URL will be used, where [:id] denotes the User ID: + "https://www.yammer.com/api/v1/users/[:id].json" + + + Refer to: https://developer.yammer.com/restapi/ for full documentation. + + + + + + Thread-safe In memory UserAuth data store so it can be used without a dependency on Redis. + + + + + Creates the required missing tables or DB schema + + + + + Create new Registration + + + + + Logic to update UserAuth from Registration info, not enabled on OnPut because of security. + + + + + Thank you Martijn + http://www.dijksterhuis.org/creating-salted-hash-values-in-c/ + + + + + Create an app at https://dev.twitter.com/apps to get your ConsumerKey and ConsumerSecret for your app. + The Callback URL for your app should match the CallbackUrl provided. + + + + + The ServiceStack Yammer OAuth provider. + + + + This provider is loosely based on the existing ServiceStack's Facebook OAuth provider. + + + For the full info on Yammer's OAuth2 authentication flow, refer to: + https://developer.yammer.com/authentication/#a-oauth2 + + + Note: Add these to your application / web config settings under appSettings and replace + values as appropriate. + + + + + + + + + ]]> + + + + + + The OAuth provider name / identifier. + + + + + Initializes a new instance of the class. + + + The application settings (in web.config). + + + + + Authenticate against Yammer OAuth endpoint. + + + The auth service. + + + The session. + + + The request. + + + The . + + + + + Load the UserAuth info into the session. + + + The User session. + + + The OAuth tokens. + + + The auth info. + + + + + Load the UserOAuth info into the session. + + + The auth session. + + + The OAuth tokens. + + + + + Gets or sets the Yammer OAuth client id. + + + + + Gets or sets the Yammer OAuth client secret. + + + + + Gets or sets the Yammer OAuth pre-auth url. + + + + + The Yammer User's email addresses. + + + + + Gets or sets the email address type (e.g. primary). + + + + + Gets or sets the email address. + + + + + Removes items from cache that have keys matching the specified wildcard pattern + + Cache client + The wildcard, where "*" means any sequence of characters and "?" means any single character. + + + + Removes items from the cache based on the specified regular expression pattern + + Cache client + Regular expression pattern to search cache keys + + + + Add value with specified key to the cache, and set the cache entry to never expire. + + + + + Stores The value with key only if such key doesn't exist at the server yet. + + + + + Adds or replaces the value with key, and sets the cache entry to never expire. + + + + + Adds or replaces the value with key. + + + + + Adds or replaces the value with key. + + + + + Replace the value with specified key if it exists, and set the cache entry to never expire. + + + + + Replace the value with specified key if it exists. + + + + + Add the value with key to the cache, set to never expire. + + + + + Add or replace the value with key to the cache, set to never expire. + + + + + Replace the value with key in the cache, set to never expire. + + + + + Add the value with key to the cache, set to expire at specified DateTime. + + This method examines the DateTimeKind of expiresAt to determine if conversion to + universal time is needed. The version of Add that takes a TimeSpan expiration is faster + than using this method with a DateTime of Kind other than Utc, and is not affected by + ambiguous local time during daylight savings/standard time transition. + + + + Add or replace the value with key to the cache, set to expire at specified DateTime. + + This method examines the DateTimeKind of expiresAt to determine if conversion to + universal time is needed. The version of Set that takes a TimeSpan expiration is faster + than using this method with a DateTime of Kind other than Utc, and is not affected by + ambiguous local time during daylight savings/standard time transition. + + + + Replace the value with key in the cache, set to expire at specified DateTime. + + This method examines the DateTimeKind of expiresAt to determine if conversion to + universal time is needed. The version of Replace that takes a TimeSpan expiration is faster + than using this method with a DateTime of Kind other than Utc, and is not affected by + ambiguous local time during daylight savings/standard time transition. + + + + Add the value with key to the cache, set to expire after specified TimeSpan. + + + + + Add or replace the value with key to the cache, set to expire after specified TimeSpan. + + + + + Replace the value with key in the cache, set to expire after specified TimeSpan. + + + + + Create new instance of CacheEntry. + + + + UTC time at which CacheEntry expires. + + + + Would've preferred to use [assembly: ContractNamespace] attribute but it is not supported in Mono + + + + + More familiar name for the new crowd. + + + + + The tier lets you specify a retrieving a setting with the tier prefix first before falling back to the original key. + E.g a tier of 'Live' looks for 'Live.{Key}' or if not found falls back to '{Key}'. + + + + + Returns string if exists, otherwise null + + + + + + + Provides a common interface for Settings providers such as + ConfigurationManager or Azure's RoleEnvironment. The only + requirement is that if the implementation cannot find the + specified key, the return value must be null + + The key for the setting + The string value of the specified key, or null if the key + was invalid + + + + Gets the nullable app setting. + + + + + Gets the app setting. + + + + + Determines wheter the Config section identified by the sectionName exists. + + + + + Returns AppSetting[key] if exists otherwise defaultValue + + + + + Returns AppSetting[key] if exists otherwise defaultValue, for non-string values + + + + + Gets the connection string setting. + + + + + Gets the connection string. + + + + + Gets the list from app setting. + + + + + Gets the dictionary from app setting. + + + + + Get the static Parse(string) method on the type supplied + + + + + Gets the constructor info for T(string) if exists. + + + + + Returns the value returned by the 'T.Parse(string)' method if exists otherwise 'new T(string)'. + e.g. if T was a TimeSpan it will return TimeSpan.Parse(textValue). + If there is no Parse Method it will attempt to create a new instance of the destined type + + + + + Plugin adds support for Cross-origin resource sharing (CORS, see http://www.w3.org/TR/access-control/). + CORS allows to access resources from different domain which usually forbidden by origin policy. + + + + + Represents a default constructor with Allow Origin equals to "*", Allowed GET, POST, PUT, DELETE, OPTIONS request and allowed "Content-Type" header. + + + + + Attribute marks that specific response class has support for Cross-origin resource sharing (CORS, see http://www.w3.org/TR/access-control/). CORS allows to access resources from different domain which usually forbidden by origin policy. + + + + + Represents a default constructor with Allow Origin equals to "*", Allowed GET, POST, PUT, DELETE, OPTIONS request and allowed "Content-Type" header. + + + + + Change the default HTML view or template used for the HTML response of this service + + + + + Class that can be used to find all the validators from a collection of types. + + + + + Creates a scanner that works on a sequence of types. + + + + + Finds all the validators in the specified assembly. + + + + + Finds all the validators in the assembly containing the specified type. + + + + + Performs the specified action to all of the assembly scan results. + + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + 1 + + + + Result of performing a scan. + + + + + Creates an instance of an AssemblyScanResult. + + + + + Validator interface type, eg IValidator<Foo> + + + + + Concrete type that implements the InterfaceType, eg FooValidator. + + + + + Implementation of IValidatorFactory that looks for ValidatorAttribute instances on the specified type in order to provide the validator instance. + + + + + Gets validators for a particular type. + + + + + Gets the validator for the specified type. + + + + + Gets the validator for the specified type. + + + + + Gets a validator for the appropriate type. + + + + + Gets a validator for the appropriate type. + + + + + Validator attribute to define the class that will describe the Validation rules + + + + + Creates an instance of the ValidatorAttribute allowing a validator type to be specified. + + + + + The type of the validator used to validate the current type. + + + + + Associates an instance of IValidator with the current property rule and is used to validate each item within the collection. + + The validator to use + + + + Rule builder + + + + + + + Rule builder + + + + + + + Associates a validator with this the property for this rule builder. + + The validator to set + + + + + Associates an instance of IValidator with the current property rule. + + The validator to use + + + + Represents an object that is configurable. + + Type of object being configured + Return type + + + + Configures the current object. + + Action to configure the object. + + + + + Extension methods that provide the default set of validators. + + + + + Defines a 'not null' validator on the current rule builder. + Validation will fail if the property is null. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + + + + + Defines a 'not empty' validator on the current rule builder. + Validation will fail if the property is null, an empty or the default value for the type (for example, 0 for integers) + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + + + + + Defines a length validator on the current rule builder, but only for string properties. + Validation will fail if the length of the string is outside of the specifed range. The range is inclusive. + + Type of object being validated + The rule builder on which the validator should be defined + + + + + Defines a length validator on the current rule builder, but only for string properties. + Validation will fail if the length of the string is not equal to the length specified. + + Type of object being validated + The rule builder on which the validator should be defined + + + + + Defines a regular expression validator on the current rule builder, but only for string properties. + Validation will fail if the value returned by the lambda does not match the regular expression. + + Type of object being validated + The rule builder on which the validator should be defined + The regular expression to check the value against. + + + + + Defines a regular expression validator on the current rule builder, but only for string properties. + Validation will fail if the value returned by the lambda is not a valid email address. + + Type of object being validated + The rule builder on which the validator should be defined + + + + + Defines a 'not equal' validator on the current rule builder. + Validation will fail if the specified value is equal to the value of the property. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value to compare + Equality comparer to use + + + + + Defines a 'not equal' validator on the current rule builder using a lambda to specify the value. + Validation will fail if the value returned by the lambda is equal to the value of the property. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression to provide the comparison value + Equality Comparer to use + + + + + Defines an 'equals' validator on the current rule builder. + Validation will fail if the specified value is not equal to the value of the property. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value to compare + Equality Comparer to use + + + + + Defines an 'equals' validator on the current rule builder using a lambda to specify the comparison value. + Validation will fail if the value returned by the lambda is not equal to the value of the property. + + The type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression to provide the comparison value + Equality comparer to use + + + + + Defines a predicate validator on the current rule builder using a lambda expression to specify the predicate. + Validation will fail if the specified lambda returns false. + Validation will succeed if the specifed lambda returns true. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression specifying the predicate + + + + + Defines a predicate validator on the current rule builder using a lambda expression to specify the predicate. + Validation will fail if the specified lambda returns false. + Validation will succeed if the specifed lambda returns true. + This overload accepts the object being validated in addition to the property being validated. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression specifying the predicate + + + + + Defines a predicate validator on the current rule builder using a lambda expression to specify the predicate. + Validation will fail if the specified lambda returns false. + Validation will succeed if the specifed lambda returns true. + This overload accepts the object being validated in addition to the property being validated. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda expression specifying the predicate + + + + + Defines a 'less than' validator on the current rule builder. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than' validator on the current rule builder. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than' validator on the current rule builder. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than or equal' validator on the current rule builder. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'greater than or equal' validator on the current rule builder. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda that should return the value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than the specified value. + The validation will fail if the property value is greater than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + A lambda that should return the value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than or equal' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is less than or equal to the specified value. + The validation will fail if the property value is greater than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than the specified value. + The validation will fail if the property value is less than or equal to the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Defines a 'less than' validator on the current rule builder using a lambda expression. + The validation will succeed if the property value is greater than or equal the specified value. + The validation will fail if the property value is less than the specified value. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The value being compared + + + + + Validates certain properties of the specified instance. + + The current validator + The object to validate + Expressions to specify the properties to validate + A ValidationResult object containing any validation failures + + + + Validates certain properties of the specified instance. + + The object to validate + The names of the properties to validate. + A ValidationResult object containing any validation failures. + + + + Performs validation and then throws an exception if validation fails. + + + + + Defines an 'inclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is inclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines an 'inclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is inclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines an 'exclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is exclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines an 'exclusive between' validator on the current rule builder, but only for properties of types that implement IComparable. + Validation will fail if the value of the property is outside of the specifed range. The range is exclusive. + + Type of object being validated + Type of property being validated + The rule builder on which the validator should be defined + The lowest allowed value + The highest allowed value + + + + + Defines a credit card validator for the current rule builder that ensures that the specified string is a valid credit card number. + + + + + Default options that can be used to configure a validator. + + + + + Specifies the cascade mode for failures. + If set to 'Stop' then execution of the rule will stop once the first validator in the chain fails. + If set to 'Continue' then all validators in the chain will execute regardless of failures. + + + + + Specifies a custom action to be invoked when the validator fails. + + + + + + + + + + Specifies a custom error message to use if validation fails. + + The current rule + The error message to use + + + + + Specifies a custom error message to use if validation fails. + + The current rule + The error message to use + Additional arguments to be specified when formatting the custom error message. + + + + + Specifies a custom error message to use if validation fails. + + The current rule + The error message to use + Additional property values to be included when formatting the custom error message. + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + Custom message format args + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + Custom message format args + + + + + Specifies a custom error message resource to use when validation fails. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + The resource accessor builder to use. + + + + + Specifies a custom error code to use when validation fails + + The current rule + The error code to use + + + + + Specifies a condition limiting when the validator should run. + The validator will only be executed if the result of the lambda returns true. + + The current rule + A lambda expression that specifies a condition for when the validator should run + Whether the condition should be applied to the current rule or all rules in the chain + + + + + Specifies a condition limiting when the validator should not run. + The validator will only be executed if the result of the lambda returns false. + + The current rule + A lambda expression that specifies a condition for when the validator should not run + Whether the condition should be applied to the current rule or all rules in the chain + + + + + Specifies a custom property name to use within the error message. + + The current rule + The property name to use + + + + + Specifies a localized name for the error message. + + The current rule + The resource to use as an expression, eg () => Messages.MyResource + Resource accessor builder to use + + + + Overrides the name of the property associated with this rule. + NOTE: This is a considered to be an advanced feature. 99% of the time that you use this, you actually meant to use WithName. + + The current rule + The property name to use + + + + + Specifies custom state that should be stored alongside the validation message when validation fails for this rule. + + + + + + + + + + Specifies how rules should cascade when one fails. + + + + + When a rule fails, execution continues to the next rule. + + + + + When a rule fails, validation is stopped and all other rules in the chain will not be executed. + + + + + Specifies where a When/Unless condition should be applied + + + + + Applies the condition to all validators declared so far in the chain. + + + + + Applies the condition to the current validator only. + + + + + Validator implementation that allows rules to be defined without inheriting from AbstractValidator. + + + + public class Customer { + public int Id { get; set; } + public string Name { get; set; } + + public static readonly InlineValidator<Customer> Validator = new InlineValidator<Customer> { + v => v.RuleFor(x => x.Name).NotNull(), + v => v.RuleFor(x => x.Id).NotEqual(0), + } + } + + + + + + + Allows configuration of the validator. + + + + + Delegate that specifies configuring an InlineValidator. + + + + + Default validator selector that will execute all rules that do not belong to a RuleSet. + + + + + Determines whether or not a rule should execute. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Custom IValidationRule for performing custom logic. + + + + + + Defines a rule associated with a property which can have multiple validators. + + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + The validators that are grouped under this rule. + + + + + Name of the rule-set to which this rule belongs. + + + + + Creates a new DelegateValidator using the specified function to perform validation. + + + + + Creates a new DelegateValidator using the specified function to perform validation. + + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + Rule set to which this rule belongs. + + + + + The validators that are grouped under this rule. + + + + + Useful extensions + + + + + Gets a MemberInfo from a member expression. + + + + + Gets a MemberInfo from a member expression. + + + + + Splits pascal case, so "FooBar" would become "Foo Bar" + + + + + Helper method to construct a constant expression from a constant. + + Type of object being validated + Type of property being validated + The value being compared + + + + + Based on a child validator and a propery rule, infers whether the validator should be wrapped in a ChildValidatorAdaptor or a CollectionValidatorAdaptor + + + + + Instancace cache. + TODO: This isn't actually completely thread safe. It would be much better to use ConcurrentDictionary, but this isn't available in Silverlight/WP7. + + + + + Gets or creates an instance using Activator.CreateInstance + + The type to instantiate + The instantiated object + + + + Gets or creates an instance using a custom factory + + The type to instantiate + The custom factory + The instantiated object + + + + Selects validators that are associated with a particular property. + + + + + Creates a new instance of MemberNameValidatorSelector. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Creates a MemberNameValidatorSelector from a collection of expressions. + + + + + Assists in the construction of validation messages. + + + + + Default Property Name placeholder. + + + + + Adds a value for a validation message placeholder. + + + + + + + + Appends a property name to the message. + + The name of the property + + + + + Adds additional arguments to the message for use with standard string placeholders. + + Additional arguments + + + + + Constructs the final message from the specified template. + + Message template + The message with placeholders replaced with their appropriate values + + + + Represents a chain of properties + + + + + Creates a new PropertyChain. + + + + + Creates a new PropertyChain based on another. + + + + + Adds a MemberInfo instance to the chain + + Member to add + + + + Adds a property name to the chain + + Name of the property to add + + + + Adds an indexer to the property chain. For example, if the following chain has been constructed: + Parent.Child + then calling AddIndexer(0) would convert this to: + Parent.Child[0] + + + + + + Creates a string representation of a property chain. + + + + + Checks if the current chain is the child of another chain. + For example, if chain1 were for "Parent.Child" and chain2 were for "Parent.Child.GrandChild" then + chain2.IsChildChainOf(chain1) would be true. + + The parent chain to compare + True if the current chain is the child of the other chain, otherwise false + + + + Builds a property path. + + + + + Defines a rule associated with a property. + + + + + Creates a new property rule. + + Property + Function to get the property value + Lambda expression used to create the rule + Function to get the cascade mode. + Type to validate + Container type that owns the property + + + + Creates a new property rule from a lambda expression. + + + + + Creates a new property rule from a lambda expression. + + + + + Adds a validator to the rule. + + + + + Replaces a validator in this rule. Used to wrap validators. + + + + + Display name for the property. + + + + + Performs validation using a validation context and returns a collection of Validation Failures. + + Validation Context + A collection of validation failures + + + + Invokes a property validator using the specified validation context. + + + + + Property associated with this rule. + + + + + Function that can be invoked to retrieve the value of the property. + + + + + Expression that was used to create the rule. + + + + + String source that can be used to retrieve the display name (if null, falls back to the property name) + + + + + Rule set that this rule belongs to (if specified) + + + + + Function that will be invoked if any of the validators associated with this rule fail. + + + + + The current validator being configured by this rule. + + + + + Type of the property being validated + + + + + Cascade mode for this rule. + + + + + Validators associated with this rule. + + + + + Returns the property name for the property being validated. + Returns null if it is not a property being validated (eg a method call) + + + + + Builds a validation rule and constructs a validator. + + Type of object being validated + Type of property being validated + + + + Rule builder that starts the chain + + + + + + + Creates a new instance of the RuleBuilder class. + + + + + Sets the validator associated with the rule. + + The validator to set + + + + + Sets the validator associated with the rule. Use with complex properties where an IValidator instance is already declared for the property type. + + The validator to set + + + + The rule being created by this RuleBuilder. + + + + + Selects validators that belong to the specified rulesets. + + + + + Creates a new instance of the RulesetValidatorSelector. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Provides metadata about a validator. + + + + + Gets the name display name for a property. + + + + + Gets a collection of validators grouped by property. + + + + + Gets validators for a particular property. + + + + + Gets rules for a property. + + + + + Builds a delegate for retrieving a localised resource from a resource type and property name. + + + + + Gets a function that can be used to retrieve a message from a resource type and resource name. + + + + + Builds a delegate for retrieving a localised resource from a resource type and property name. + + + + + Builds a function used to retrieve the resource. + + + + + Gets the PropertyInfo for a resource. + ResourceType and ResourceName are ref parameters to allow derived types + to replace the type/name of the resource before the delegate is constructed. + + + + + Implemenetation of IResourceAccessorBuilder that can fall back to the default resource provider. + + + + + Gets the PropertyInfo for a resource. + ResourceType and ResourceName are ref parameters to allow derived types + to replace the type/name of the resource before the delegate is constructed. + + + + + Provides error message templates + + + + + Construct the error message template + + Error message template + + + + The name of the resource if localized. + + + + + The type of the resource provider if localized. + + + + + Represents a localized string. + + + + + Creates a new instance of the LocalizedErrorMessageSource class using the specified resource name and resource type. + + The resource type + The resource name + Strategy used to construct the resource accessor + + + + Creates an IErrorMessageSource from an expression: () => MyResources.SomeResourceName + + The expression + Strategy used to construct the resource accessor + Error message source + + + + Construct the error message template + + Error message template + + + + The name of the resource if localized. + + + + + The type of the resource provider if localized. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to '{PropertyName}' is not a valid credit card number.. + + + + + Looks up a localized string similar to '{PropertyName}' is not a valid email address.. + + + + + Looks up a localized string similar to '{PropertyName}' should be equal to '{PropertyValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be {MaxLength} characters in length. You entered {TotalLength} characters.. + + + + + Looks up a localized string similar to '{PropertyName}' must be between {From} and {To} (exclusive). You entered {Value}.. + + + + + Looks up a localized string similar to '{PropertyName}' must be greater than '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be greater than or equal to '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be between {From} and {To}. You entered {Value}.. + + + + + Looks up a localized string similar to '{PropertyName}' must be between {MinLength} and {MaxLength} characters. You entered {TotalLength} characters.. + + + + + Looks up a localized string similar to '{PropertyName}' must be less than '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must be less than or equal to '{ComparisonValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' should not be empty.. + + + + + Looks up a localized string similar to '{PropertyName}' should not be equal to '{PropertyValue}'.. + + + + + Looks up a localized string similar to '{PropertyName}' must not be empty.. + + + + + Looks up a localized string similar to The specified condition was not met for '{PropertyName}'.. + + + + + Looks up a localized string similar to '{PropertyName}' is not in the correct format.. + + + + + Represents a static string. + + + + + Creates a new StringErrorMessageSource using the specified error message as the error template. + + The error message template. + + + + Construct the error message template + + Error message template + + + + The name of the resource if localized. + + + + + The type of the resource provider if localized. + + + + + Creates a new validation failure. + + + + + Creates a new ValidationFailure. + + + + + Creates a textual representation of the failure. + + + + + The name of the property. + + + + + The error message + + + + + The error code + + + + + The property value that caused the failure. + + + + + Custom state associated with the failure. + + + + + Used for providing metadata about a validator. + + + + + A custom property validator. + This interface should not be implemented directly in your code as it is subject to change. + Please inherit from PropertyValidator instead. + + + + + Creates an error validation result for this validator. + + The validator context + Returns an error validation result. + + + + Ensures that the property value is a valid credit card number. + + + + + Provides access to the anti-forgery system, which provides protection against + Cross-site Request Forgery (XSRF, also called CSRF) attacks. + + + + + Generates an anti-forgery token for this request. This token can + be validated by calling the Validate() method. + + An HTML string corresponding to an <input type="hidden"> + element. This element should be put inside a <form>. + + This method has a side effect: it may set a response cookie. + + + + + Generates an anti-forgery token pair (cookie and form token) for this request. + This method is similar to GetHtml(), but this method gives the caller control + over how to persist the returned values. To validate these tokens, call the + appropriate overload of Validate. + + The anti-forgery token - if any - that already existed + for this request. May be null. The anti-forgery system will try to reuse this cookie + value when generating a matching form token. + Will contain a new cookie value if the old cookie token + was null or invalid. If this value is non-null when the method completes, the caller + must persist this value in the form of a response cookie, and the existing cookie value + should be discarded. If this value is null when the method completes, the existing + cookie value was valid and needn't be modified. + The value that should be stored in the <form>. The caller + should take care not to accidentally swap the cookie and form tokens. + + Unlike the GetHtml() method, this method has no side effect. The caller + is responsible for setting the response cookie and injecting the returned + form token as appropriate. + + + + + Validates an anti-forgery token that was supplied for this request. + The anti-forgery token may be generated by calling GetHtml(). + + + Throws an HttpAntiForgeryException if validation fails. + + + + + Validates an anti-forgery token pair that was generated by the GetTokens method. + + The token that was supplied in the request cookie. + The token that was supplied in the request form body. + + Throws an HttpAntiForgeryException if validation fails. + + + + + Provides programmatic configuration for the anti-forgery token system. + + + + + Specifies an object that can provide additional data to put into all + generated tokens and that can validate additional data in incoming + tokens. + + + + + Specifies the name of the cookie that is used by the anti-forgery + system. + + + If an explicit name is not provided, the system will automatically + generate a name. + + + + + Specifies whether SSL is required for the anti-forgery system + to operate. If this setting is 'true' and a non-SSL request + comes into the system, all anti-forgery APIs will fail. + + + + + Specifies whether the anti-forgery system should skip checking + for conditions that might indicate misuse of the system. Please + use caution when setting this switch, as improper use could open + security holes in the application. + + + Setting this switch will disable several checks, including: + - Identity.IsAuthenticated = true without Identity.Name being set + - special-casing claims-based identities + + + + + If claims-based authorization is in use, specifies the claim + type from the identity that is used to uniquely identify the + user. If this property is set, all claims-based identities + must return unique values for this claim type. + + + If claims-based authorization is in use and this property has + not been set, the anti-forgery system will automatically look + for claim types "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" + and "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider". + + + + + Allows providing or validating additional custom data for anti-forgery tokens. + For example, the developer could use this to supply a nonce when the token is + generated, then he could validate the nonce when the token is validated. + + + The anti-forgery system already embeds the client's username within the + generated tokens. This interface provides and consumes supplemental + data. If an incoming anti-forgery token contains supplemental data but no + additional data provider is configured, the supplemental data will not be + validated. + + + + + Provides additional data to be stored for the anti-forgery tokens generated + during this request. + + Information about the current request. + Supplemental data to embed within the anti-forgery token. + + + + Validates additional data that was embedded inside an incoming anti-forgery + token. + + Information about the current request. + Supplemental data that was embedded within the token. + True if the data is valid; false if the data is invalid. + + + + Initializes a new instance of the class. + + The base scope. + + The dictionary to use as a storage. Since the dictionary would be used as-is, we expect the implementer to + use the same key-value comparison logic as we do here. + + + + + Custom comparer for the context dictionaries + The comparer treats strings as a special case, performing case insesitive comparison. + This guaratees that we remain consistent throughout the chain of contexts since PageData dictionary + behaves in this manner. + + + + + End a ServiceStack Request + + + + + End a ServiceStack Request + + + + + End a HttpHandler Request + + + + + End a HttpHandler Request + + + + + End a ServiceStack Request with no content + + + + + Main container class for components, supporting container hierarchies and + lifetime management of instances. + + + + + Initializes a new empty container. + + + + + Creates a child container of the current one, which exposes its + current service registration to the new child container. + + + + + Disposes the container and all instances owned by it (see + ), as well as all child containers + created through . + + + + + Registers a service instance with the container. This instance + will have and + behavior. + Service instance to use. + + + + Registers a named service instance with the container. This instance + will have and + behavior. + Name of the service to register.Service instance to use. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service when needed. + Type of the service to retrieve.The function that can resolve to the service instance when invoked.The requested service has not been registered previously. + + + + + + + + + + + + + + + + + + + + + + Retrieves a function that can be used to lazily resolve an instance + of the service with the given name when needed. + Type of the service to retrieve.Name of the service to retrieve.The function that can resolve to the service instance with the given name when invoked.The requested service with the given name has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Retrieves a function that can be used to lazily resolve an instance + of the service of the given type, name and service constructor arguments when needed. + Name of the service to retrieve.The function that can resolve to the service instance with the given and service constructor arguments name when invoked.The requested service with the given name and constructor arguments has not been registered previously. + + + + Registers the given service by providing a factory delegate to + instantiate it. + The service type to register.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.Sixth argument that should be passed to the factory delegate to create the instace.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate to + instantiate it. + The service type to register.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Registers the given named service by providing a factory delegate that receives arguments to + instantiate it. + The service type to register.First argument that should be passed to the factory delegate to create the instace.Second argument that should be passed to the factory delegate to create the instace.Third argument that should be passed to the factory delegate to create the instace.Fourth argument that should be passed to the factory delegate to create the instace.Fifth argument that should be passed to the factory delegate to create the instace.Sixth argument that should be passed to the factory delegate to create the instace.A name used to differenciate this service registration.The factory delegate to initialize new instances of the service when needed.The registration object to perform further configuration via its fluent interface. + + + + Resolves the given service by type, without passing any arguments for + its construction. + Type of the service to retrieve.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, without passing arguments for its initialization. + Type of the service to retrieve.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Resolves the given service by type and name, passing the given arguments + for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace.The resolved service instance.The given service could not be resolved. + + + + Attempts to resolve the given service by type, without passing arguments for its initialization. + Type of the service to retrieve. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, without passing + arguments arguments for its initialization. + Type of the service to retrieve. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Attempts to resolve the given service by type and name, passing the + given arguments arguments for its initialization. + Type of the service to retrieve.First argument to pass to the factory delegate that may create the instace.Second argument to pass to the factory delegate that may create the instace.Third argument to pass to the factory delegate that may create the instace.Fourth argument to pass to the factory delegate that may create the instace.Fifth argument to pass to the factory delegate that may create the instace.Sixth argument to pass to the factory delegate that may create the instace. + The resolved service instance or if it cannot be resolved. + + + + + Register an autowired dependency + + + + + + Register an autowired dependency as a separate type + + + + + + Alias for RegisterAutoWiredAs + + + + + + Auto-wires an existing instance, + ie all public properties are tried to be resolved. + + + + + + Generates a function which creates and auto-wires . + + + + + + + + Auto-wires an existing instance of a specific type. + The auto-wiring progress is also cached to be faster + when calling next time with the same type. + + + + + + Default owner for new registrations. by default. + + + + + Default reuse scope for new registrations. by default. + + + + + Enable the Registration feature and configure the RegistrationService. + + + + + Registers the type in the IoC container and + adds auto-wiring to the specified type. + + + + + + + Registers the type in the IoC container and + adds auto-wiring to the specified type. + The reuse scope is set to none (transient). + + + + + + Registers the types in the IoC container and + adds auto-wiring to the specified types. + The reuse scope is set to none (transient). + + + + + + Register a singleton instance as a runtime type + + + + + Encapsulates a method that has five parameters and returns a value of the + type specified by the parameter. + + + + + Encapsulates a method that has six parameters and returns a value of the + type specified by the parameter. + + + + + Encapsulates a method that has seven parameters and returns a value of the + type specified by the parameter. + + + + + Helper interface used to hide the base + members from the fluent API to make for much cleaner + Visual Studio intellisense experience. + + + + + + + + + + + + + + + + + Interface used by plugins to contribute registrations + to an existing container. + + + + + Determines who is responsible for disposing instances + registered with a container. + + + + + Container should dispose provided instances when it is disposed. This is the + default. + + + + + Container does not dispose provided instances. + + + + + Default owner, which equals . + + + + + Exception thrown by the container when a service cannot be resolved. + + + + + Initializes the exception with the service that could not be resolved. + + + + + Initializes the exception with the service (and its name) that could not be resolved. + + + + + Initializes the exception with an arbitrary message. + + + + + Determines visibility and reuse of instances provided by the container. + + + + + Instances are reused within a container hierarchy. Instances + are created (if necessary) in the container where the registration + was performed, and are reused by all descendent containers. + + + + + Instances are reused only at the given container. Descendent + containers do not reuse parent container instances and get + a new instance at their level. + + + + + Each request to resolve the dependency will result in a new + instance being returned. + + + + + Instaces are reused within the given request + + + + + Default scope, which equals . + + + + + Fluent API for customizing the registration of a service. + + + + + Fluent API that exposes both + and owner (). + + + + + Fluent API that allows specifying the reuse instances. + + + + + Specifies how instances are reused within a container or hierarchy. Default + scope is . + + + + + Fluent API that allows specifying the owner of instances + created from a registration. + + + + + Specifies the owner of instances created from this registration. Default + owner is . + + + + + Ownership setting for the service. + + + + + Reuse scope setting for the service. + + + + + The container where the entry was registered. + + + + + Specifies the owner for instances, which determines how + they will be disposed. + + + + + Specifies the scope for instances, which determines + visibility of instances across containers and hierarchies. + + + + + Fluent API for customizing the registration of a service. + + + + + Fluent API that allows registering an initializer for the + service. + + + + + Specifies an initializer that should be invoked after + the service instance has been created by the factory. + + + + + The Func delegate that creates instances of the service. + + + + + The cached service instance if the scope is or + . + + + + + The Func delegate that initializes the object after creation. + + + + + Clones the service entry assigning the to the + . Does not copy the . + + + + + BaseProfilerProvider. This providers some helper methods which provide access to + internals not otherwise available. + To use, override the , and + methods. + + + + + A provider used to create instances and maintain the current instance. + + + + + Starts a new MiniProfiler and sets it to be current. By the end of this method + should return the new MiniProfiler. + + + + + Ends the current profiling session, if one exists. + + + When true, clears the for this HttpContext, allowing profiling to + be prematurely stopped and discarded. Useful for when a specific route does not need to be profiled. + + + + + Returns the current MiniProfiler. This is used by . + + + + + + Starts a new MiniProfiler and sets it to be current. By the end of this method + should return the new MiniProfiler. + + + + + Stops the current MiniProfiler (if any is currently running). + should be called if is false + + If true, any current results will be thrown away and nothing saved + + + + Returns the current MiniProfiler. This is used by . + + + + + + Sets to be active (read to start profiling) + This should be called once a new MiniProfiler has been created. + + The profiler to set to active + If is null + + + + Stops the profiler and marks it as inactive. + + The profiler to stop + True if successful, false if Stop had previously been called on this profiler + If is null + + + + Calls to save the current + profiler using the current storage settings + + + + + + Categories of sql statements. + + + + + Unknown + + + + + DML statements that alter database state, e.g. INSERT, UPDATE + + + + + Statements that return a single record + + + + + Statements that iterate over a result set + + + + + A callback for ProfiledDbConnection and family + + + + + Called when a command starts executing + + + + + + + Called when a reader finishes executing + + + + + + + + Called when a reader is done iterating through the data + + + + + + Called when an error happens during execution of a command + + + + + + + + True if the profiler instance is active + + + + + This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), + and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE** + equality. The type is fully thread-safe. + + + + + If the underlying command supports BindByName, this sets/clears the underlying + implementation accordingly. This is required to support OracleCommand from dapper-dot-net + + + + + Wraps a database connection, allowing sql execution timings to be collected when a session is started. + + + + + This will be made private; use + + + + + This will be made private; use + + + + + Returns a new that wraps , + providing query execution profiling. If profiler is null, no profiling will occur. + + Your provider-specific flavor of connection, e.g. SqlConnection, OracleConnection + The currently started or null. + Determines whether the ProfiledDbConnection will dispose the underlying connection. + + + + The underlying, real database connection to your db provider. + + + + + The current profiler instance; could be null. + + + + + The raw connection this is wrapping + + + + + Wrapper for a db provider factory to enable profiling + + + + + Every provider factory must have an Instance public field + + + + + Used for db provider apis internally + + + + + Allow to re-init the provider factory. + + + + + + + proxy + + + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + proxy + + + + + Common extension methods to use only in this project + + + + + Answers true if this String is either null or empty. + + + + + Answers true if this String is neither null or empty. + + + + + Removes trailing / characters from a path and leaves just one + + + + + Removes any leading / characters from a path + + + + + Removes any leading / characters from a path + + + + + Serializes to a json string. + + + + + Gets part of a stack trace containing only methods we care about. + + + + + Gets the current formatted and filted stack trace. + + Space separated list of methods + + + + Identifies users based on ip address. + + + + + Provides functionality to identify which user is profiling a request. + + + + + Returns a string to identify the user profiling the current 'request'. + + The current HttpRequest being profiled. + + + + Returns the paramter HttpRequest's client ip address. + + + + + A single MiniProfiler can be used to represent any number of steps/levels in a call-graph, via Step() + + Totally baller. + + + + Starts when this profiler is instantiated. Each step will use this Stopwatch's current ticks as + their starting time. + + + + + Creates and starts a new MiniProfiler for the root , filtering steps to . + + + + + Returns the 's and this profiler recorded. + + + + + Returns true if Ids match. + + + + + Returns hashcode of Id. + + + + + Obsolete - used for serialization. + + + + + Walks the hierarchy contained in this profiler, starting with , and returns each Timing found. + + + + + Returns milliseconds based on Stopwatch's Frequency. + + + + + Starts a new MiniProfiler based on the current . This new profiler can be accessed by + + + + + + Ends the current profiling session, if one exists. + + + When true, clears the for this HttpContext, allowing profiling to + be prematurely stopped and discarded. Useful for when a specific route does not need to be profiled. + + + + + Returns an that will time the code between its creation and disposal. Use this method when you + do not wish to include the MvcMiniProfiler namespace for the extension method. + + A descriptive name for the code that is encapsulated by the resulting IDisposable's lifetime. + This step's visibility level; allows filtering when is called. + + + + Returns the css and javascript includes needed to display the MiniProfiler results UI. + + Which side of the page the profiler popup button should be displayed on (defaults to left) + Whether to show trivial timings by default (defaults to false) + Whether to show time the time with children column by default (defaults to false) + The maximum number of trace popups to show before removing the oldest (defaults to 15) + xhtml rendering mode, ensure script tag is closed ... etc + when true, shows buttons to minimize and clear MiniProfiler results + Script and link elements normally; an empty string when there is no active profiling session. + + + + Renders the current to json. + + + + + Renders the parameter to json. + + + + + Deserializes the json string parameter to a . + + + + + Create a DEEP clone of this object + + + + + + Returns all currently open commands on this connection + + + + + Returns all results contained in all child steps. + + + + + Contains any sql statements that are executed, along with how many times those statements are executed. + + + + + Adds to the current . + + + + + Returns the number of sql statements of that were executed in all s. + + + + + Identifies this Profiler so it may be stored/cached. + + + + + A display name for this profiling session. + + + + + When this profiler was instantiated. + + + + + Where this profiler was run. + + + + + Allows filtering of steps based on what + the steps are created with. + + + + + The first that is created and started when this profiler is instantiated. + All other s will be children of this one. + + + + + A string identifying the user/client that is profiling this request. Set + with an -implementing class to provide a custom value. + + + If this is not set manually at some point, the implementation will be used; + by default, this will be the current request's ip address. + + + + + Returns true when this MiniProfiler has been viewed by the that recorded it. + + + Allows POSTs that result in a redirect to be profiled. implementation + will keep a list of all profilers that haven't been fetched down. + + + + + For unit testing, returns the timer. + + + + + Milliseconds, to one decimal place, that this MiniProfiler ran. + + + + + Returns true when or any of its are . + + + + + Returns true when all child s are . + + + + + Any Timing step with a duration less than or equal to this will be hidden by default in the UI; defaults to 2.0 ms. + + + + + Ticks since this MiniProfiler was started. + + + + + Json representing the collection of CustomTimings relating to this Profiler + + + Is used when storing the Profiler in SqlStorage + + + + + Points to the currently executing Timing. + + + + + Gets the currently running MiniProfiler for the current HttpContext; null if no MiniProfiler was ed. + + + + + Contains information about queries executed during this profiling session. + + + + + Milliseconds, to one decimal place, that this MiniProfiler was executing sql. + + + + + Returns true when we have profiled queries. + + + + + Returns true when any child Timings have duplicate queries. + + + + + How many sql data readers were executed in all steps. + + + + + How many sql scalar queries were executed in all steps. + + + + + How many sql non-query statements were executed in all steps. + + + + + Various configuration properties. + + + + + Excludes the specified assembly from the stack trace output. + + The short name of the assembly. AssemblyName.Name + + + + Excludes the specified type from the stack trace output. + + The System.Type name to exclude + + + + Excludes the specified method name from the stack trace output. + + The name of the method + + + + Make sure we can at least store profiler results to the http runtime cache. + + + + + Assemblies to exclude from the stack trace report. + + + + + Types to exclude from the stack trace report. + + + + + Methods to exclude from the stack trace report. + + + + + The max length of the stack string to report back; defaults to 120 chars. + + + + + Any Timing step with a duration less than or equal to this will be hidden by default in the UI; defaults to 2.0 ms. + + + + + Dictates if the "time with children" column is displayed by default, defaults to false. + For a per-page override you can use .RenderIncludes(showTimeWithChildren: true/false) + + + + + Dictates if trivial timings are displayed by default, defaults to false. + For a per-page override you can use .RenderIncludes(showTrivial: true/false) + + + + + Determines how many traces to show before removing the oldest; defaults to 15. + For a per-page override you can use .RenderIncludes(maxTracesToShow: 10) + + + + + Dictates on which side of the page the profiler popup button is displayed; defaults to left. + For a per-page override you can use .RenderIncludes(position: RenderPosition.Left/Right) + + + + + Determines if min-max, clear, etc are rendered; defaults to false. + For a per-page override you can use .RenderIncludes(showControls: true/false) + + + + + By default, SqlTimings will grab a stack trace to help locate where queries are being executed. + When this setting is true, no stack trace will be collected, possibly improving profiler performance. + + + + + When is called, if the current request url contains any items in this property, + no profiler will be instantiated and no results will be displayed. + Default value is { "/ssr-", "/content/", "/scripts/", "/favicon.ico" }. + + + + + The path under which ALL routes are registered in, defaults to the application root. For example, "~/myDirectory/" would yield + "/myDirectory/ssr-includes.js" rather than just "/mini-profiler-includes.js" + Any setting here should be in APP RELATIVE FORM, e.g. "~/myDirectory/" + + + + + Understands how to save and load MiniProfilers. Used for caching between when + a profiling session ends and results can be fetched to the client, and for showing shared, full-page results. + + + The normal profiling session life-cycle is as follows: + 1) request begins + 2) profiler is started + 3) normal page/controller/request execution + 4) profiler is stopped + 5) profiler is cached with 's implementation of + 6) request ends + 7) page is displayed and profiling results are ajax-fetched down, pulling cached results from + 's implementation of + + + + + The formatter applied to the SQL being rendered (used only for UI) + + + + + Assembly version of this dank MiniProfiler. + + + + + The provider used to provider the current instance of a provider + This is also + + + + + A function that determines who can access the MiniProfiler results url. It should return true when + the request client has access, false for a 401 to be returned. HttpRequest parameter is the current request and + MiniProfiler parameter is the results that were profiled. + + + Both the HttpRequest and MiniProfiler parameters that will be passed into this function should never be null. + + + + + Allows switching out stopwatches for unit testing. + + + + + Categorizes individual steps to allow filtering. + + + + + Default level given to Timings. + + + + + Useful when profiling many items in a loop, but you don't wish to always see this detail. + + + + + Dictates on which side of the page the profiler popup button is displayed; defaults to left. + + + + + Profiler popup button is displayed on the left. + + + + + Profiler popup button is displayed on the right. + + + + + Contains helper methods that ease working with null s. + + + + + Wraps in a call and executes it, returning its result. + + The current profiling session or null. + Method to execute and profile. + The step name used to label the profiler results. + + + + + Returns an that will time the code between its creation and disposal. + + The current profiling session or null. + A descriptive name for the code that is encapsulated by the resulting IDisposable's lifetime. + This step's visibility level; allows filtering when is called. + + + + Adds 's hierarchy to this profiler's current Timing step, + allowing other threads, remote calls, etc. to be profiled and joined into this profiling session. + + + + + Returns an html-encoded string with a text-representation of ; returns "" when profiler is null. + + The current profiling session or null. + + + + Formats any SQL query with inline parameters, optionally including the value type + + + + + Takes a SqlTiming and returns a formatted SQL string, for parameter replacement, etc. + + + + + Return SQL the way you want it to look on the in the trace. Usually used to format parameters + + + Formatted SQL + + + + Creates a new Inline SQL Formatter, optionally including the parameter type info in comments beside the replaced value + + whether to include a comment after the value, indicating the type, e.g. /* @myParam DbType.Int32 */ + + + + Formats the SQL in a generic frieldly format, including the parameter type information in a comment if it was specified in the InlineFormatter constructor + + The SqlTiming to format + A formatted SQL string + + + + Returns a string representation of the parameter's value, including the type + + The parameter to get a value for + + + + + NOT IMPLEMENTED - will format statements with paramters in an Oracle friendly way + + + + + Does NOTHING, implement me! + + + + + Formats SQL server queries with a DECLARE up top for parameter values + + + + + Formats the SQL in a SQL-Server friendly way, with DECLARE statements for the parameters up top. + + The SqlTiming to format + A formatted SQL string + + + + Contains helper code to time sql statements. + + + + + Returns a new SqlProfiler to be used in the 'profiler' session. + + + + + Tracks when 'command' is started. + + + + + Returns all currently open commands on this connection + + + + + Finishes profiling for 'command', recording durations. + + + + + Called when 'reader' finishes its iterations and is closed. + + + + + The profiling session this SqlProfiler is part of. + + + + + Helper methods that allow operation on SqlProfilers, regardless of their instantiation. + + + + + Tracks when 'command' is started. + + + + + Finishes profiling for 'command', recording durations. + + + + + Called when 'reader' finishes its iterations and is closed. + + + + + Profiles a single sql execution. + + + + + Creates a new SqlTiming to profile 'command'. + + + + + Obsolete - used for serialization. + + + + + Returns a snippet of the sql command and the duration. + + + + + Returns true if Ids match. + + + + + Returns hashcode of Id. + + + + + Called when command execution is finished to determine this SqlTiming's duration. + + + + + Called when database reader is closed, ending profiling for SqlTimings. + + + + + To help with display, put some space around sammiched commas + + + + + Unique identifier for this SqlTiming. + + + + + Category of sql statement executed. + + + + + The sql that was executed. + + + + + The command string with special formatting applied based on MiniProfiler.Settings.SqlFormatter + + + + + Roughly where in the calling code that this sql was executed. + + + + + Offset from main MiniProfiler start that this sql began. + + + + + How long this sql statement took to execute. + + + + + When executing readers, how long it took to come back initially from the database, + before all records are fetched and reader is closed. + + + + + Stores any parameter names and values used by the profiled DbCommand. + + + + + Id of the Timing this statement was executed in. + + + Needed for database deserialization. + + + + + The Timing step that this sql execution occurred in. + + + + + True when other identical sql statements have been executed during this MiniProfiler session. + + + + + Information about a DbParameter used in the sql statement profiled by SqlTiming. + + + + + Returns true if this has the same parent , and as . + + + + + Returns the XOR of certain properties. + + + + + Which SqlTiming this Parameter was executed with. + + + + + Parameter name, e.g. "@routeName" + + + + + The value submitted to the database. + + + + + System.Data.DbType, e.g. "String", "Bit" + + + + + How large the type is, e.g. for string, size could be 4000 + + + + + Understands how to save MiniProfiler results to a MSSQL database, allowing more permanent storage and + querying of slow results. + + + + + Provides saving and loading s to a storage medium. + + + + + Stores under its . + + The results of a profiling session. + + Should also ensure the profiler is stored as being unviewed by its profiling . + + + + + Returns a from storage based on , which should map to . + + + Should also update that the resulting profiler has been marked as viewed by its profiling . + + + + + Returns a list of s that haven't been seen by . + + User identified by the current . + + + + Returns a new SqlServerDatabaseStorage object that will insert into the database identified by connectionString. + + + + + Saves 'profiler' to a database under its . + + + + + Returns the MiniProfiler identified by 'id' from the database or null when no MiniProfiler exists under that 'id'. + + + + + Returns a list of s that haven't been seen by . + + User identified by the current . + + + + Returns a DbConnection for your specific provider. + + + + + Returns a DbConnection already opened for execution. + + + + + How we connect to the database used to save/load MiniProfiler results. + + + + + Understands how to store a to the with absolute expiration. + + + + + The string that prefixes all keys that MiniProfilers are saved under, e.g. + "mini-profiler-ecfb0050-7ce8-4bf1-bf82-2cb38e90e31e". + + + + + Returns a new HttpRuntimeCacheStorage class that will cache MiniProfilers for the specified duration. + + + + + Saves to the HttpRuntime.Cache under a key concated with + and the parameter's . + + + + + Returns the saved identified by . Also marks the resulting + profiler to true. + + + + + Returns a list of s that haven't been seen by . + + User identified by the current . + + + + Syncs access to runtime cache when adding a new list of ids for a user. + + + + + How long to cache each for (i.e. the absolute expiration parameter of + ) + + + + + An individual profiling step that can contain child steps. + + + + + Rebuilds all the parent timings on deserialization calls + + + + + Offset from parent MiniProfiler's creation that this Timing was created. + + + + + Creates a new Timing named 'name' in the 'profiler's session, with 'parent' as this Timing's immediate ancestor. + + + + + Obsolete - used for serialization. + + + + + Returns this Timing's Name. + + + + + Returns true if Ids match. + + + + + Returns hashcode of Id. + + + + + Adds arbitrary string 'value' under 'key', allowing custom properties to be stored in this Timing step. + + + + + Completes this Timing's duration and sets the MiniProfiler's Head up one level. + + + + + Add the parameter 'timing' to this Timing's Children collection. + + + Used outside this assembly for custom deserialization when creating an implementation. + + + + + Adds the parameter 'sqlTiming' to this Timing's SqlTimings collection. + + A sql statement profiling that was executed in this Timing step. + + Used outside this assembly for custom deserialization when creating an implementation. + + + + + Returns the number of sql statements of that were executed in this . + + + + + Unique identifer for this timing; set during construction. + + + + + Text displayed when this Timing is rendered. + + + + + How long this Timing step took in ms; includes any Timings' durations. + + + + + The offset from the start of profiling. + + + + + All sub-steps that occur within this Timing step. Add new children through + + + + + Stores arbitrary key/value strings on this Timing step. Add new tuples through . + + + + + Any queries that occurred during this Timing step. + + + + + Needed for database deserialization and JSON serialization. + + + + + Which Timing this Timing is under - the duration that this step takes will be added to its parent's duration. + + This will be null for the root (initial) Timing. + + + + Gets the elapsed milliseconds in this step without any children's durations. + + + + + Gets the aggregate elapsed milliseconds of all SqlTimings executed in this Timing, excluding Children Timings. + + + + + Returns true when this is less than the configured + , by default 2.0 ms. + + + + + Reference to the containing profiler, allowing this Timing to affect the Head and get Stopwatch readings. + + + + + Returns true when this Timing has inner Timing steps. + + + + + Returns true if this Timing step collected sql execution timings. + + + + + Returns true if any s executed in this step are detected as duplicate statements. + + + + + Returns true when this Timing is the first one created in a MiniProfiler session. + + + + + How far away this Timing is from the Profiler's Root. + + + + + How many sql data readers were executed in this Timing step. Does not include queries in any child Timings. + + + + + How many sql scalar queries were executed in this Timing step. Does not include queries in any child Timings. + + + + + How many sql non-query statements were executed in this Timing step. Does not include queries in any child Timings. + + + + + Understands how to route and respond to MiniProfiler UI urls. + + + + + Returns either includes' css/javascript or results' html. + + + + + Handles rendering static content files. + + + + + Handles rendering a previous MiniProfiler session, identified by its "?id=GUID" on the query. + + + + + Embedded resource contents keyed by filename. + + + + + Helper method that sets a proper 404 response code. + + + + + Try to keep everything static so we can easily be reused. + + + + + HttpContext based profiler provider. This is the default provider to use in a web context. + The current profiler is associated with a HttpContext.Current ensuring that profilers are + specific to a individual HttpRequest. + + + + + Public constructor. This also registers any UI routes needed to display results + + + + + Starts a new MiniProfiler and associates it with the current . + + + + + Ends the current profiling session, if one exists. + + + When true, clears the for this HttpContext, allowing profiling to + be prematurely stopped and discarded. Useful for when a specific route does not need to be profiled. + + + + + Makes sure 'profiler' has a Name, pulling it from route data or url. + + + + + Returns the current profiler + + + + + + Gets the currently running MiniProfiler for the current HttpContext; null if no MiniProfiler was ed. + + + + + WebRequestProfilerProvider specific configurations + + + + + Provides user identification for a given profiling request. + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has specific permissions. + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has specific roles. + + + + + Check all session is in all supplied roles otherwise a 401 HttpError is thrown + + + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has specific permissions. + + + + + Indicates that the request dto, which is associated with this attribute, + can only execute, if the user has any of the specified roles. + + + + + Check all session is in any supplied roles otherwise a 401 HttpError is thrown + + + + + + + Base class to create response filter attributes only for specific HTTP methods (GET, POST...) + + + + + Creates a new + + Defines when the filter should be executed + + + + This method is only executed if the HTTP method matches the property. + + The http request wrapper + The http response wrapper + The response DTO + + + + Create a ShallowCopy of this instance. + + + + + + If they don't have an ICacheClient configured use an In Memory one. + + + + + Creates instance using straight Resolve approach. + This will throw an exception if resolution fails + + + + + Creates instance using the TryResolve approach if tryResolve = true. + Otherwise uses Resolve approach, which will throw an exception if resolution fails + + + + + Sets a persistent cookie which never expires + + + + + Sets a session cookie which expires after the browser session closes + + + + + Deletes a specified cookie by setting its value to empty and expiration to -1 days + + + + + Lets you Register new Services and the optional restPaths will be registered against + this default Request Type + + + + + Naming convention for the ResponseStatus property name on the response DTO + + + + + Create an instance of the service response dto type and inject it with the supplied responseStatus + + + + + + + + + + + + + + + + + Override to provide additional/less context about the Service Exception. + By default the request is serialized and appended to the ResponseStatus StackTrace. + + + + + Scans the supplied Assemblies to infer REST paths and HTTP verbs. + + The instance. + + The assemblies with REST services. + + The same instance; + never . + + + + Configure ServiceStack to have ISession support + + + + + Create the active Session or Permanent Session Id cookie. + + + + + + Create both Permanent and Session Id cookies and return the active sessionId + + + + + + This class interecepts 401 requests and changes them to 402 errors. When this happens the FormAuthentication module + will no longer hijack it and redirect back to login because it is a 402 error, not a 401. + When the request ends, this class sets the status code back to 401 and everything works as it should. + + PathToSupress is the path inside your website where the above swap should happen. + + If you can build for .net 4.5, you do not have to do this swap. You can take advantage of a new flag (SuppressFormsAuthenticationRedirect) + that tells the FormAuthenticationModule to not redirect, which also means you will not need the EndRequest code. + + + + + Converts the validation result to an error result which will be serialized by ServiceStack in a clean and human-readable way. + + The validation result + + + + + Converts the validation result to an error exception which will be serialized by ServiceStack in a clean and human-readable way + if the returned exception is thrown. + + The validation result + + + + + Creates a new instance of the RulesetValidatorSelector. + + + + + Determines whether or not a rule should execute. + + The rule + Property path (eg Customer.Address.Line1) + Contextual information + Whether or not the validator can execute. + + + + Activate the validation mechanism, so every request DTO with an existing validator + will be validated. + + The app host + + + + Override to provide additional/less context about the Service Exception. + By default the request is serialized and appended to the ResponseStatus StackTrace. + + + + + Auto-scans the provided assemblies for a + and registers it in the provided IoC container. + + The IoC container + The assemblies to scan for a validator + + + + In Memory repository for files. Useful for testing. + + + + + Context to capture IService action + + + + + Get an IAppHost container. + Note: Registering dependencies should only be done during setup/configuration + stage and remain immutable there after for thread-safety. + + + + + + + Ensure the same instance is used for subclasses + + + + + Called before page is executed + + + + + Called after page is executed but before it's merged with the + website template if any. + + + + + Don't HTML encode safe output + + + + + + + Return the output of a different view with the specified name + using the supplied model + + + + + + + + Resolve registered Assemblies + + + + + + Reference to MarkdownViewEngine + + + + + The AppHost so you can access configuration and resolve dependencies, etc. + + + + + This precompiled Markdown page with Metadata + + + + + ASP.NET MVC's HtmlHelper + + + + + All variables passed to and created by your page. + The Response DTO is stored and accessible via the 'Model' variable. + + All variables and outputs created are stored in ScopeArgs which is what's available + to your website template. The Generated page is stored in the 'Body' variable. + + + + + Whether HTML or Markdown output is requested + + + + + The Response DTO + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to Container service is built-in and read-only.. + + + + + Looks up a localized string similar to Service type {0} does not inherit or implement {1}.. + + + + + Looks up a localized string similar to Required dependency of type {0} named '{1}' could not be resolved.. + + + + + Looks up a localized string similar to Required dependency of type {0} could not be resolved.. + + + + + Looks up a localized string similar to Unknown scope.. + + + + + Gets string value from Items[name] then Cookies[name] if exists. + Useful when *first* setting the users response cookie in the request filter. + To access the value for this initial request you need to set it in Items[]. + + string value or null if it doesn't exist + + + + Gets request paramater string value by looking in the following order: + - QueryString[name] + - FormData[name] + - Cookies[name] + - Items[name] + + string value or null if it doesn't exist + + + * + Input: http://localhost:96/Cambia3/Temp/Test.aspx/path/info?q=item#fragment + + Some HttpRequest path and URL properties: + Request.ApplicationPath: /Cambia3 + Request.CurrentExecutionFilePath: /Cambia3/Temp/Test.aspx + Request.FilePath: /Cambia3/Temp/Test.aspx + Request.Path: /Cambia3/Temp/Test.aspx/path/info + Request.PathInfo: /path/info + Request.PhysicalApplicationPath: D:\Inetpub\wwwroot\CambiaWeb\Cambia3\ + Request.QueryString: /Cambia3/Temp/Test.aspx/path/info?query=arg + Request.Url.AbsolutePath: /Cambia3/Temp/Test.aspx/path/info + Request.Url.AbsoluteUri: http://localhost:96/Cambia3/Temp/Test.aspx/path/info?query=arg + Request.Url.Fragment: + Request.Url.Host: localhost + Request.Url.LocalPath: /Cambia3/Temp/Test.aspx/path/info + Request.Url.PathAndQuery: /Cambia3/Temp/Test.aspx/path/info?query=arg + Request.Url.Port: 96 + Request.Url.Query: ?query=arg + Request.Url.Scheme: http + Request.Url.Segments: / + Cambia3/ + Temp/ + Test.aspx/ + path/ + info + * + + + + Use this to treat Request.Items[] as a cache by returning pre-computed items to save + calculating them multiple times. + + + + + Sets a persistent cookie which never expires + + + + + Sets a session cookie which expires after the browser session closes + + + + + Sets a persistent cookie which expires after the given time + + + + + Sets a persistent cookie with an expiresAt date + + + + + Deletes a specified cookie by setting its value to empty and expiration to -1 days + + + + + Returns the optimized result for the IRequestContext. + Does not use or store results in any cache. + + + + + + + + Overload for the method returning the most + optimized result based on the MimeType and CompressionType from the IRequestContext. + + + + + Overload for the method returning the most + optimized result based on the MimeType and CompressionType from the IRequestContext. + How long to cache for, null is no expiration + + + + + Clears all the serialized and compressed caches set + by the 'Resolve' method for the cacheKey provided + + + + + + + + Store an entry in the IHttpRequest.Items Dictionary + + + + + Get an entry from the IHttpRequest.Items Dictionary + + + + + For performance withPathInfoParts should already be a lower case string + to minimize redundant matching operations. + + + + + + + + For performance withPathInfoParts should already be a lower case string + to minimize redundant matching operations. + + + + + + + + + The number of segments separated by '/' determinable by path.Split('/').Length + e.g. /path/to/here.ext == 3 + + + + + The total number of segments after subparts have been exploded ('.') + e.g. /path/to/here.ext == 4 + + + + + Provide for quick lookups based on hashes that can be determined from a request url + + + + + Execute MQ + + + + + Execute MQ with requestContext + + + + + Execute using empty RequestContext + + + + + Execute HTTP + + + + + Gets the name of the base most type in the heirachy tree with the same. + + We get an exception when trying to create a schema with multiple types of the same name + like when inheriting from a DataContract with the same name. + + The type. + + + + + Inherit from this class if you want to host your web services inside an + ASP.NET application. + + + + + Exécute les tâches définies par l'application associées à la libération ou à la redéfinition des ressources non managées. + + 2 + + + + Load Embedded Resource Templates in ServiceStack. + To get ServiceStack to use your own instead just add a copy of one or more of the following to your Web Root: + ~/Templates/IndexOperations.html + ~/Templates/OperationControl.html + ~/Templates/HtmlFormat.html + + + + + when true, (most) bare plain URLs are auto-hyperlinked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, RETURN becomes a literal newline + WARNING: this is a significant deviation from the markdown spec + + + + + use ">" for HTML output, or " />" for XHTML output + + + + + when true, problematic URL characters like [, ], (, and so forth will be encoded + WARNING: this is a significant deviation from the markdown spec + + + + + when false, email addresses will never be auto-linked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, bold and italic require non-word characters on either side + WARNING: this is a significant deviation from the markdown spec + + + + + Markdown is a text-to-HTML conversion tool for web writers. + Markdown allows you to write using an easy-to-read, easy-to-write plain text format, + then convert it to structurally valid XHTML (or HTML). + + + + + Tabs are automatically converted to spaces as part of the transform + this constant determines how "wide" those tabs become in spaces + + + + + Create a new Markdown instance using default options + + + + + Create a new Markdown instance and optionally load options from a configuration + file. There they should be stored in the appSettings section, available options are: + + Markdown.StrictBoldItalic (true/false) + Markdown.EmptyElementSuffix (">" or " />" without the quotes) + Markdown.LinkEmails (true/false) + Markdown.AutoNewLines (true/false) + Markdown.AutoHyperlink (true/false) + Markdown.EncodeProblemUrlCharacters (true/false) + + + + + + Create a new Markdown instance and set the options from the MarkdownOptions object. + + + + + maximum nested depth of [] and () supported by the transform; implementation detail + + + + + In the static constuctor we'll initialize what stays the same across all transforms. + + + + + Transforms the provided Markdown-formatted text to HTML; + see http://en.wikipedia.org/wiki/Markdown + + + The order in which other subs are called here is + essential. Link and image substitutions need to happen before + EscapeSpecialChars(), so that any *'s or _'s in the a + and img tags get encoded. + + + + + Perform transformations that form block-level tags like paragraphs, headers, and list items. + + + + + Perform transformations that occur *within* block-level tags like paragraphs, headers, and list items. + + + + + splits on two or more newlines, to form "paragraphs"; + each paragraph is then unhashed (if it is a hash and unhashing isn't turned off) or wrapped in HTML p tag + + + + + Reusable pattern to match balanced [brackets]. See Friedl's + "Mastering Regular Expressions", 2nd Ed., pp. 328-331. + + + + + Reusable pattern to match balanced (parens). See Friedl's + "Mastering Regular Expressions", 2nd Ed., pp. 328-331. + + + + + Strips link definitions from text, stores the URLs and titles in hash references. + + + ^[id]: url "optional title" + + + + + derived pretty much verbatim from PHP Markdown + + + + + replaces any block-level HTML blocks with hash entries + + + + + returns an array of HTML tokens comprising the input string. Each token is + either a tag (possibly with nested, tags contained therein, such + as <a href="<MTFoo>">, or a run of text between tags. Each element of the + array is a two-element array; the first is either 'tag' or 'text'; the second is + the actual value. + + + + + Turn Markdown link shortcuts into HTML anchor tags + + + [link text](url "title") + [link text][id] + [id] + + + + + Turn Markdown image shortcuts into HTML img tags. + + + ![alt text][id] + ![alt text](url "optional title") + + + + + Turn Markdown headers into HTML header tags + + + Header 1 + ======== + + Header 2 + -------- + + # Header 1 + ## Header 2 + ## Header 2 with closing hashes ## + ... + ###### Header 6 + + + + + Turn Markdown horizontal rules into HTML hr tags + + + *** + * * * + --- + - - - + + + + + Turn Markdown lists into HTML ul and ol and li tags + + + + + Process the contents of a single ordered or unordered list, splitting it + into individual list items. + + + + + /// Turn Markdown 4-space indented code into HTML pre code blocks + + + + + Turn Markdown `code spans` into HTML code tags + + + + + Turn Markdown *italics* and **bold** into HTML strong and em tags + + + + + Turn markdown line breaks (two space at end of line) into HTML break tags + + + + + Turn Markdown > quoted blocks into HTML blockquote blocks + + + + + Turn angle-delimited URLs into HTML anchor tags + + + <http://www.example.com> + + + + + Remove one level of line-leading spaces + + + + + encodes email address randomly + roughly 10% raw, 45% hex, 45% dec + note that @ is always encoded and : never is + + + + + Encode/escape certain Markdown characters inside code blocks and spans where they are literals + + + + + Encode any ampersands (that aren't part of an HTML entity) and left or right angle brackets + + + + + Encodes any escaped characters such as \`, \*, \[ etc + + + + + swap back in all the special characters we've hidden + + + + + escapes Bold [ * ] and Italic [ _ ] characters + + + + + hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems + + + + + Within tags -- meaning between < and > -- encode [\ ` * _] so they + don't conflict with their use in Markdown for code, italics and strong. + We're replacing each such character with its corresponding hash + value; this is likely overkill, but it should prevent us from colliding + with the escape values by accident. + + + + + convert all tabs to _tabWidth spaces; + standardizes line endings from DOS (CR LF) or Mac (CR) to UNIX (LF); + makes sure text ends with a couple of newlines; + removes any blank lines (only spaces) in the text + + + + + this is to emulate what's evailable in PHP + + + + + use ">" for HTML output, or " />" for XHTML output + + + + + when false, email addresses will never be auto-linked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, bold and italic require non-word characters on either side + WARNING: this is a significant deviation from the markdown spec + + + + + when true, RETURN becomes a literal newline + WARNING: this is a significant deviation from the markdown spec + + + + + when true, (most) bare plain URLs are auto-hyperlinked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, problematic URL characters like [, ], (, and so forth will be encoded + WARNING: this is a significant deviation from the markdown spec + + + + + current version of MarkdownSharp; + see http://code.google.com/p/markdownsharp/ for the latest code or to contribute + + + + + Render Markdown for text/markdown and text/plain ContentTypes + + + + + Used in Unit tests + + + + + + Non ASP.NET requests + + + + + + + + ASP.NET requests + + + + + + Writes to response. + Response headers are customizable by implementing IHasOptions an returning Dictionary of Http headers. + + The response. + Whether or not it was implicity handled by ServiceStack's built-in handlers. + The default action. + The serialization context. + Add prefix to response body if any + Add suffix to response body if any + + + + + Highly optimized code to find if GZIP is supported from: + - http://dotnetperls.com/gzip-request + + Other resources for GZip, deflate resources: + - http://www.west-wind.com/Weblog/posts/10564.aspx + - http://www.west-wind.com/WebLog/posts/102969.aspx + - ICSharpCode + + + + + Changes the links for the servicestack/metadata page + + + + + Non ASP.NET requests + + + + + ASP.NET requests + + + + + Keep default file contents in-memory + + + + + + Call to signal the completion of a ServiceStack-handled Request + + + + + Resolves and auto-wires a ServiceStack Service from a ASP.NET HttpContext. + + + + + Resolves and auto-wires a ServiceStack Service from a HttpListenerContext. + + + + + Resolves and auto-wires a ServiceStack Service. + + + + diff --git a/src/Docs/packages/ServiceStack.Client.4.0.11/ServiceStack.Client.4.0.11.nupkg b/src/Docs/packages/ServiceStack.Client.4.0.11/ServiceStack.Client.4.0.11.nupkg new file mode 100644 index 00000000..729cf384 Binary files /dev/null and b/src/Docs/packages/ServiceStack.Client.4.0.11/ServiceStack.Client.4.0.11.nupkg differ diff --git a/src/Docs/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.dll b/src/Docs/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.dll new file mode 100644 index 00000000..661af9fb Binary files /dev/null and b/src/Docs/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.dll differ diff --git a/src/Docs/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.xml b/src/Docs/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.xml new file mode 100644 index 00000000..1811c5ff --- /dev/null +++ b/src/Docs/packages/ServiceStack.Client.4.0.11/lib/net40/ServiceStack.Client.xml @@ -0,0 +1,383 @@ + + + + ServiceStack.Client + + + + Need to provide async request options + http://msdn.microsoft.com/en-us/library/86wf6409(VS.71).aspx + + + + The request filter is called before any request. + This request filter is executed globally. + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + This response action is executed globally. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Called before request resend, when the initial request required authentication + + + + + The request filter is called before any request. + This request filter only works with the instance where it was set (not global). + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Returns the next message from queueName or null if no message + + + + + + + Generic Proxy for service calls. + + The service Contract + + + + Returns the transparent proxy for the service call + + + + Need to provide async request options + http://msdn.microsoft.com/en-us/library/86wf6409(VS.71).aspx + + + + The request filter is called before any request. + This request filter is executed globally. + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + This response action is executed globally. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Sets all baseUri properties, using the Format property for the SyncReplyBaseUri and AsyncOneWayBaseUri + + Base URI of the service + + + + Whether to Accept Gzip,Deflate Content-Encoding and to auto decompress responses + + + + + The user name for basic authentication + + + + + The password for basic authentication + + + + + Sets the username and the password for basic authentication. + + + + + Determines if the basic auth header should be sent with every request. + By default, the basic auth header is only sent when "401 Unauthorized" is returned. + + + + + Specifies if cookies should be stored + + + + + Called by Send method if an exception occurs, for instance a System.Net.WebException because the server + returned an HTTP error code. Override if you want to handle specific exceptions or always want to parse the + response to a custom ErrorResponse DTO type instead of ServiceStack's ErrorResponse class. In case ex is a + System.Net.WebException, do not use + createWebRequest/getResponse/HandleResponse<TResponse> to parse the response + because that will result in the same exception again. Use + ThrowWebServiceException<YourErrorResponseType> to parse the response and to throw a + WebServiceException containing the parsed DTO. Then override Send to handle that exception. + + + + + Gets the collection of headers to be added to outgoing requests. + + + + + Gets or sets authentication information for the request. + Warning: It's recommened to use and for basic auth. + This property is only used for IIS level authentication. + + + + + Called before request resend, when the initial request required authentication + + + + + The request filter is called before any request. + This request filter only works with the instance where it was set (not global). + + + + + The response action is called once the server response is available. + It will allow you to access raw response information. + Note that you should NOT consume the response stream as this is handled by ServiceStack + + + + + Track any IDisposable's to dispose of at the end of the request in IAppHost.OnEndRequest() + + + + + + Gets a list of items for this request. + + This list will be cleared on every request and is specific to the original thread that is handling the request. + If a handler uses additional threads, this data will not be available on those threads. + + + + + Creates the error response from the values provided. + + If the errorCode is empty it will use the first validation error code, + if there is none it will throw an error. + + The error code. + The error message. + The validation errors. + + + + + Default MaxStringContentLength is 8k, and throws an exception when reached + + + + + Serializer cache of delegates required to create a type from a string map (e.g. for REST urls) + + + + + Gets the namespace from an attribute marked on the type's definition + + + Namespace of type + + + + Specifies if cookies should be stored + + + + + Compresses the specified text using the default compression method: Deflate + + The text. + Type of the compression. + + + + + Decompresses the specified gz buffer using the default compression method: Inflate + + The gz buffer. + Type of the compression. + + + + + Donated by Ivan Korneliuk from his post: + http://korneliuk.blogspot.com/2012/08/servicestack-reusing-dtos.html + + Modified to only allow using routes matching the supplied HTTP Verb + + + + + Generate a url from a Request DTO. Pretty URL generation require Routes to be defined using `[Route]` on the Request DTO + + + + + The exception which is thrown when a validation error occurred. + This validation is serialized in a extra clean and human-readable way by ServiceStack. + + + + + Used if we need to serialize this exception to XML + + + + + + Returns the first error code + + The error code. + + + + Encapsulates a validation result. + + + + + Constructs a new ValidationResult + + + + + Constructs a new ValidationResult + + A list of validation results + + + + Initializes a new instance of the class. + + The errors. + The success code. + The error code. + + + + Merge errors from another + + + + + + Gets or sets the success code. + + The success code. + + + + Gets or sets the error code. + + The error code. + + + + Gets or sets the success message. + + The success message. + + + + Gets or sets the error message. + + The error message. + + + + The errors generated by the validation. + + + + + Returns True if the validation was successful (errors list is empty). + + + + + Adds the singleton instance of to an endpoint on the client. + + + Based on http://megakemp.wordpress.com/2009/02/06/managing-shared-cookies-in-wcf/ + + + + + Adds the singleton of the class to the client endpoint's message inspectors. + + The endpoint that is to be customized. + The client runtime to be customized. + + + + Maintains a copy of the cookies contained in the incoming HTTP response received from any service + and appends it to all outgoing HTTP requests. + + + This class effectively allows to send any received HTTP cookies to different services, + reproducing the same functionality available in ASMX Web Services proxies with the class. + Based on http://megakemp.wordpress.com/2009/02/06/managing-shared-cookies-in-wcf/ + + + + + Initializes a new instance of the class. + + + + + Inspects a message after a reply message is received but prior to passing it back to the client application. + + The message to be transformed into types and handed back to the client application. + Correlation state data. + + + + Inspects a message before a request message is sent to a service. + + The message to be sent to the service. + The client object channel. + + Null since no message correlation is used. + + + + + Gets the singleton instance. + + + + + Naming convention for the request's Response DTO + + + + + Shortcut to get the ResponseStatus whether it's bare or inside a IHttpResult + + + + + + diff --git a/src/Docs/packages/ServiceStack.Client.4.0.11/lib/sl5/ServiceStack.Client.dll b/src/Docs/packages/ServiceStack.Client.4.0.11/lib/sl5/ServiceStack.Client.dll new file mode 100644 index 00000000..51628a91 Binary files /dev/null and b/src/Docs/packages/ServiceStack.Client.4.0.11/lib/sl5/ServiceStack.Client.dll differ diff --git a/src/Docs/packages/ServiceStack.Common.4.0.11/ServiceStack.Common.4.0.11.nupkg b/src/Docs/packages/ServiceStack.Common.4.0.11/ServiceStack.Common.4.0.11.nupkg new file mode 100644 index 00000000..050eb691 Binary files /dev/null and b/src/Docs/packages/ServiceStack.Common.4.0.11/ServiceStack.Common.4.0.11.nupkg differ diff --git a/src/Docs/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.dll b/src/Docs/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.dll new file mode 100644 index 00000000..4c7a5afb Binary files /dev/null and b/src/Docs/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.dll differ diff --git a/src/Docs/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.xml b/src/Docs/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.xml new file mode 100644 index 00000000..109d91cf --- /dev/null +++ b/src/Docs/packages/ServiceStack.Common.4.0.11/lib/net40/ServiceStack.Common.xml @@ -0,0 +1,206 @@ + + + + ServiceStack.Common + + + + + Useful .NET Encryption Utils from: + http://andrewlocatelliwoodcock.com/2011/08/01/implementing-rsa-asymmetric-public-private-key-encryption-in-c-encrypting-under-the-public-key/ + + + + + Encrypt an arbitrary string of data under the supplied public key + + The public key to encrypt under + The data to encrypt + The bit length or strength of the public key: 1024, 2048 or 4096 bits. This must match the + value actually used to create the publicKey + + + + + Create Public and Private Key Pair based on settings already in static class. + + RsaKeyPair + + + + Gets the textual description of the enum if it has one. e.g. + + + enum UserColors + { + [Description("Bright Red")] + BrightRed + } + UserColors.BrightRed.ToDescription(); + + + + + + + + Creates a Console Logger, that logs all messages to: System.Console + + Made public so its testable + + + + + Default logger is to Console.WriteLine + + Made public so its testable + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + + + + Useful IPAddressExtensions from: + http://blogs.msdn.com/knom/archive/2008/12/31/ip-address-calculations-with-c-subnetmasks-networks.aspx + + + + + + Gets the ipv4 addresses from all Network Interfaces that have Subnet masks. + + + + + + Gets the ipv6 addresses from all Network Interfaces. + + + + + + Func to get the Strongly-typed field + + + + + Required to cast the return ValueType to an object for caching + + + + + Func to set the Strongly-typed field + + + + + Required to cast the ValueType to an object for caching + + + + + Required to cast the ValueType to an object for caching + + + + + Func to get the Strongly-typed field + + + + + Required to cast the return ValueType to an object for caching + + + + + Func to set the Strongly-typed field + + + + + Required to cast the ValueType to an object for caching + + + + + Required to cast the ValueType to an object for caching + + + + + Common functionality when creating adapters + + + + + Executes the specified expression. + + + The action. + + + + + Executes the specified action (for void methods). + + The action. + + + + Note: InMemoryLog keeps all logs in memory, so don't use it long running exceptions + + Returns a thread-safe InMemoryLog which you can use while *TESTING* + to provide a detailed analysis of your logs. + + + + + Creates a Unified Resource Name (URN) with the following formats: + + - urn:{TypeName}:{IdFieldValue} e.g. urn:UserSession:1 + - urn:{TypeName}:{IdFieldName}:{IdFieldValue} e.g. urn:UserSession:UserId:1 + + + + + + + Provide the an option for the callee to block until all commands are executed + + + + + + + Invokes the action provided and returns true if no excpetion was thrown. + Otherwise logs the exception and returns false if an exception was thrown. + + The action. + + + + diff --git a/src/Docs/packages/ServiceStack.Interfaces.4.0.11/ServiceStack.Interfaces.4.0.11.nupkg b/src/Docs/packages/ServiceStack.Interfaces.4.0.11/ServiceStack.Interfaces.4.0.11.nupkg new file mode 100644 index 00000000..4e4fca5b Binary files /dev/null and b/src/Docs/packages/ServiceStack.Interfaces.4.0.11/ServiceStack.Interfaces.4.0.11.nupkg differ diff --git a/src/Docs/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.dll b/src/Docs/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.dll new file mode 100644 index 00000000..d13fea94 Binary files /dev/null and b/src/Docs/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.dll differ diff --git a/src/Docs/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.xml b/src/Docs/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.xml new file mode 100644 index 00000000..fd6b0866 --- /dev/null +++ b/src/Docs/packages/ServiceStack.Interfaces.4.0.11/lib/net40/ServiceStack.Interfaces.xml @@ -0,0 +1,1685 @@ + + + + ServiceStack.Interfaces + + + + + Required when using a TypeDescriptor to make it unique + + + + + A common interface implementation that is implemented by most cache providers + + + + + Removes the specified item from the cache. + + The identifier for the item to delete. + + true if the item was successfully removed from the cache; false otherwise. + + + + + Removes the cache for all the keys provided. + + The keys. + + + + Retrieves the specified item from the cache. + + + The identifier for the item to retrieve. + + The retrieved item, or null if the key was not found. + + + + + Increments the value of the specified key by the given amount. + The operation is atomic and happens on the server. + A non existent value at key starts at 0 + + The identifier for the item to increment. + The amount by which the client wants to increase the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Increments the value of the specified key by the given amount. + The operation is atomic and happens on the server. + A non existent value at key starts at 0 + + The identifier for the item to increment. + The amount by which the client wants to decrease the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Adds a new item into the cache at the specified cache key only if the cache is empty. + + The key used to reference the item. + The object to be inserted into the cache. + + true if the item was successfully stored in the cache; false otherwise. + + The item does not expire unless it is removed due memory pressure. + + + + Sets an item into the cache at the cache key specified regardless if it already exists or not. + + + + + Replaces the item at the cachekey specified only if an items exists at the location already. + + + + + Invalidates all data on the cache. + + + + + Retrieves multiple items from the cache. + The default value of T is set for all keys that do not exist. + + The list of identifiers for the items to retrieve. + + a Dictionary holding all items indexed by their key. + + + + + Sets multiple items to the cache. + + + The values. + + + + Removes items from cache that have keys matching the specified wildcard pattern + + The wildcard, where "*" means any sequence of characters and "?" means any single character. + + + + Removes items from the cache based on the specified regular expression pattern + + Regular expression pattern to search cache keys + + + + A light interface over a cache client. + This interface was inspired by Enyim.Caching.MemcachedClient + + Only the methods that are intended to be used are required, if you require + extra functionality you can uncomment the unused methods below as they have been + implemented in DdnMemcachedClient + + + + + Removes the specified item from the cache. + + The identifier for the item to delete. + + true if the item was successfully removed from the cache; false otherwise. + + + + + Removes the cache for all the keys provided. + + The keys. + + + + Retrieves the specified item from the cache. + + The identifier for the item to retrieve. + + The retrieved item, or null if the key was not found. + + + + + Increments the value of the specified key by the given amount. The operation is atomic and happens on the server. + + The identifier for the item to increment. + The amount by which the client wants to increase the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Increments the value of the specified key by the given amount. The operation is atomic and happens on the server. + + The identifier for the item to increment. + The amount by which the client wants to decrease the item. + + The new value of the item or -1 if not found. + + The item must be inserted into the cache before it can be changed. The item must be inserted as a . The operation only works with values, so -1 always indicates that the item was not found. + + + + Inserts an item into the cache with a cache key to reference its location. + + The key used to reference the item. + The object to be inserted into the cache. + + true if the item was successfully stored in the cache; false otherwise. + + The item does not expire unless it is removed due memory pressure. + + + + Inserts an item into the cache with a cache key to reference its location. + + The key used to reference the item. + The object to be inserted into the cache. + The time when the item is invalidated in the cache. + true if the item was successfully stored in the cache; false otherwise. + + + + Removes all data from the cache. + + + + + Retrieves multiple items from the cache. + + The list of identifiers for the items to retrieve. + + a Dictionary holding all items indexed by their key. + + + + + A Users Session + + + + + Set a typed value at key + + + + + + + + Get a typed value at key + + + + + + + + Store any object at key + + + + + + + Retrieves a User Session + + + + + Gets the session for this request, creates one if it doesn't exist. + + + + + + + + Gets the session for this request, creates one if it doesn't exist. + Only for ASP.NET apps. Uses the HttpContext.Current singleton. + + + + + Allow delegation of dependencies to other IOC's + + + + + Resolve Property Dependency + + + + + + + Resolve Constructor Dependency + + + + + + + BelongToAttribute + Use to indicate that a join column belongs to another table. + + + + + Compute attribute. + Use to indicate that a property is a Calculated Field + + + + + Decimal length attribute. + + + + + Explicit foreign key name. If it's null, or empty, the FK name will be autogenerated as before. + + + + + IgnoreAttribute + Use to indicate that a property is not a field in the table + properties with this attribute are ignored when building sql sentences + + + + + Primary key attribute. + use to indicate that property is part of the pk + + + + + Used to annotate an Entity with its DB schema + + + + + + For providers that want a cleaner API with a little more perf + + + + + + Decorate any type or property with adhoc info + + + + + Creates a Debug Logger, that logs all messages to: System.Diagnostics.Debug + + Made public so its testable + + + + + Factory to create ILog instances + + + + + Gets the logger. + + + + + Gets the logger. + + + + + Default logger is to System.Diagnostics.Debug.WriteLine + + Made public so its testable + + + + + Logs a message in a running application + + + + + Logs a Debug message. + + The message. + + + + Logs a Debug message and exception. + + The message. + The exception. + + + + Logs a Debug format message. + + The format. + The args. + + + + Logs a Error message. + + The message. + + + + Logs a Error message and exception. + + The message. + The exception. + + + + Logs a Error format message. + + The format. + The args. + + + + Logs a Fatal message. + + The message. + + + + Logs a Fatal message and exception. + + The message. + The exception. + + + + Logs a Error format message. + + The format. + The args. + + + + Logs an Info message and exception. + + The message. + + + + Logs an Info message and exception. + + The message. + The exception. + + + + Logs an Info format message. + + The format. + The args. + + + + Logs a Warning message. + + The message. + + + + Logs a Warning message and exception. + + The message. + The exception. + + + + Logs a Warning format message. + + The format. + The args. + + + + Gets or sets a value indicating whether this instance is debug enabled. + + + true if this instance is debug enabled; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + + + + Default logger is to System.Diagnostics.Debug.Print + + Made public so its testable + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + + + + Creates a Debug Logger, that logs all messages to: System.Diagnostics.Debug + + Made public so its testable + + + + + StringBuilderLog writes to shared StringBuffer. + Made public so its testable + + + + + Logs the specified message. + + + + + Logs the format. + + + + + Logs the specified message. + + The message. + + + + Creates a test Logger, that stores all log messages in a member list + + + + + Tests logger which stores all log messages in a member list which can be examined later + + Made public so its testable + + + + + Initializes a new instance of the class. + + The type. + + + + Initializes a new instance of the class. + + The type. + + + + Logs the specified message. + + The message. + The exception. + + + + Logs the format. + + The message. + The args. + + + + Logs the specified message. + + The message. + + + + Contract indication that the Response DTO has a ResponseStatus + + + + + Logging API for this library. You can inject your own implementation otherwise + will use the DebugLogFactory to write to System.Diagnostics.Debug + + + + + Gets the logger. + + + + + Gets the logger. + + + + + Gets or sets the log factory. + Use this to override the factory that is used to create loggers + + + + + Publish the specified message into the durable queue @queueName + + + + + Publish the specified message into the transient queue @queueName + + + + + Synchronous blocking get. + + + + + Non blocking get message + + + + + Acknowledge the message has been successfully received or processed + + + + + Negative acknowledgement the message was not processed correctly + + + + + Create a typed message from a raw MQ Response artefact + + + + + Simple definition of an MQ Host + + + + + Register DTOs and hanlders the MQ Host will process + + + + + + + Register DTOs and hanlders the MQ Host will process + + + + + + + + Get Total Current Stats for all Message Handlers + + + + + + Get the status of the service. Potential Statuses: Disposed, Stopped, Stopping, Starting, Started + + + + + + Get a Stats dump + + + + + + Start the MQ Host if not already started. + + + + + Stop the MQ Host if not already stopped. + + + + + Factory to create consumers and producers that work with this service + + + + + Get a list of all message types registered on this MQ Host + + + + + Basic implementation of IMessage[T] + + + + + + Util static generic class to create unique queue names for types + + + + + + Util class to create unique queue names for runtime types + + + + + For messaging exceptions that should by-pass the messaging service's configured + retry attempts and store the message straight into the DLQ + + + + + Wrap the common redis list operations under a IList[string] interface. + + + + + Redis transaction for typed client + + + + + + interface to queueable operation using typed redis client + + + + + + Interface to redis typed pipeline + + + + + Pipeline interface shared by typed and non-typed pipelines + + + + + Interface to operations that allow queued commands to be completed + + + + + Returns a high-level typed client API + + + + + + Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly client using the hosts defined in ReadOnlyHosts. + + + + + + Returns a Read/Write ICacheClient (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly ICacheClient using the hosts defined in ReadOnlyHosts. + + + + + + Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly client using the hosts defined in ReadOnlyHosts. + + + + + + Returns a Read/Write ICacheClient (The default) using the hosts defined in ReadWriteHosts + + + + + + Returns a ReadOnly ICacheClient using the hosts defined in ReadOnlyHosts. + + + + + + Subscribe to channels by name + + + + + + Subscribe to channels matching the supplied patterns + + + + + + The number of active subscriptions this client has + + + + + Registered handler called after client *Subscribes* to each new channel + + + + + Registered handler called when each message is received + + + + + Registered handler called when each channel is unsubscribed + + + + + Interface to redis transaction + + + + + Base transaction interface, shared by typed and non-typed transactions + + + + + interface to operation that can queue commands + + + + + Interface to redis pipeline + + + + + Gets or sets parameter name with which allowable values will be associated. + + + + + The overall description of an API. Used by Swagger. + + + + + Gets or sets verb to which applies attribute. By default applies to all verbs. + + + + + Gets or sets parameter type: It can be only one of the following: path, query, body, or header. + + + + + Gets or sets unique name for the parameter. Each name must be unique, even if they are associated with different paramType values. + + + + Other notes on the name field: + If paramType is body, the name is used only for UI and codegeneration. + If paramType is path, the name field must correspond to the associated path segment from the path field in the api object. + If paramType is query, the name field corresponds to the query param name. + + + + + + Gets or sets the human-readable description for the parameter. + + + + + For path, query, and header paramTypes, this field must be a primitive. For body, this can be a complex or container datatype. + + + + + For path, this is always true. Otherwise, this field tells the client whether or not the field must be supplied. + + + + + For query params, this specifies that a comma-separated list of values can be passed to the API. For path and body types, this field cannot be true. + + + + + The status code of a response + + + + + The description of a response status code + + + + + Marker interfaces + + + + + Implement on Request DTOs that need access to the raw Request Stream + + + + + The raw Http Request Input Stream + + + + + Resolve a dependency from the AppHost's IOC + + + + + + + This interface can be implemented by an attribute + which adds an request filter for the specific request DTO the attribute marked. + + + + + The request filter is executed before the service. + + The http request wrapper + The http response wrapper + The request DTO + + + + A new shallow copy of this filter is used on every request. + + + + + + Order in which Request Filters are executed. + <0 Executed before global request filters + >0 Executed after global request filters + + + + + This interface can be implemented by an attribute + which adds an response filter for the specific response DTO the attribute marked. + + + + + The response filter is executed after the service + + The http request wrapper + The http response wrapper + + + + A new shallow copy of this filter is used on every request. + + + + + + Order in which Response Filters are executed. + <0 Executed before global response filters + >0 Executed after global response filters + + + + + The HTTP Response Status + + + + + The HTTP Response Status Code + + + + + The HTTP Status Description + + + + + The HTTP Response ContentType + + + + + Additional HTTP Headers + + + + + Response DTO + + + + + if not provided, get's injected by ServiceStack + + + + + Holds the request call context + + + + + A thin wrapper around ASP.NET or HttpListener's HttpRequest + + + + + A thin wrapper around each host's Request e.g: ASP.NET, HttpListener, MQ, etc + + + + + The entire string contents of Request.InputStream + + + + + + The underlying ASP.NET or HttpListener HttpRequest + + + + + The name of the service being called (e.g. Request DTO Name) + + + + + The Verb / HttpMethod or Action for this request + + + + + Optional preferences for the processing of this Request + + + + + The Request DTO, after it has been deserialized. + + + + + The request ContentType + + + + + The expected Response ContentType for this request + + + + + Whether the ResponseContentType has been explicitly overrided or whether it was just the default + + + + + Attach any data to this request that all filters and services can access. + + + + + Buffer the Request InputStream so it can be re-read + + + + + The Remote Ip as reported by Request.UserHostAddress + + + + + The Remote Ip as reported by X-Forwarded-For, X-Real-IP or Request.UserHostAddress + + + + + e.g. is https or not + + + + + Access to the multi-part/formdata files posted on this request + + + + + The value of the Referrer, null if not available + + + + + The HttpResponse + + + + + The HTTP Verb + + + + + The IP Address of the X-Forwarded-For header, null if null or empty + + + + + The Port number of the X-Forwarded-Port header, null if null or empty + + + + + The http or https scheme of the X-Forwarded-Proto header, null if null or empty + + + + + The value of the X-Real-IP header, null if null or empty + + + + + A thin wrapper around ASP.NET or HttpListener's HttpResponse + + + + + A thin wrapper around each host's Response e.g: ASP.NET, HttpListener, MQ, etc + + + + + Signal that this response has been handled and no more processing should be done. + When used in a request or response filter, no more filters or processing is done on this request. + + + + + Calls Response.End() on ASP.NET HttpResponse otherwise is an alias for Close(). + Useful when you want to prevent ASP.NET to provide it's own custom error page. + + + + + Response.Flush() and OutputStream.Flush() seem to have different behaviour in ASP.NET + + + + + The underlying ASP.NET or HttpListener HttpResponse + + + + + The Response DTO + + + + + Gets a value indicating whether this instance is closed. + + + + + Log every service request + + + + + Log a request + + The RequestContext + Request DTO + Response DTO or Exception + How long did the Request take + + + + View the most recent logs + + + + + + + Turn On/Off Session Tracking + + + + + Turn On/Off Raw Request Body Tracking + + + + + Turn On/Off Tracking of Responses + + + + + Turn On/Off Tracking of Exceptions + + + + + Limit access to /requestlogs service to role + + + + + Don't log requests of these types. + + + + + Don't log request bodys for services with sensitive information. + By default Auth and Registration requests are hidden. + + + + + Implement on services that need access to the RequestContext + + + + + Responsible for executing the operation within the specified context. + + The operation types. + + + + Returns the first matching RestPath + + + + + Executes the MQ DTO request. + + + + + Executes the MQ DTO request with the supplied requestContext + + + + + Executes the DTO request under the supplied requestContext. + + + + + Executes the DTO request with an empty RequestContext. + + + + + Allow the registration of user-defined routes for services + + + + + Maps the specified REST path to the specified request DTO. + + The type of request DTO to map + the path to. + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + The same instance; + never . + + + + Maps the specified REST path to the specified request DTO, and + specifies the HTTP verbs supported by the path. + + The type of request DTO to map + the path to. + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + + The comma-delimited list of HTTP verbs supported by the path, + such as "GET,PUT,DELETE". Specify empty or + to indicate that all verbs are supported. + + The same instance; + never . + + + + Maps the specified REST path to the specified request DTO, + specifies the HTTP verbs supported by the path, and indicates + the default MIME type of the returned response. + + + The type of request DTO to map the path to. + + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + + The comma-delimited list of HTTP verbs supported by the path, + such as "GET,PUT,DELETE". + + The same instance; + never . + + + + Maps the specified REST path to the specified request DTO, + specifies the HTTP verbs supported by the path, and indicates + the default MIME type of the returned response. + + + Used to rank the precedences of route definitions in reverse routing. + i.e. Priorities below 0 are auto-generated have less precedence. + + + + + Maps the specified REST path to the specified request DTO, + specifies the HTTP verbs supported by the path, and indicates + the default MIME type of the returned response. + + + The type of request DTO to map the path to. + + The path to map the request DTO to. + See RouteAttribute.Path + for details on the correct format. + + The comma-delimited list of HTTP verbs supported by the path, + such as "GET,PUT,DELETE". + + + The short summary of what the REST does. + + + The longer text to explain the behaviour of the REST. + + The same instance; + never . + + + + Used to decorate Request DTO's to associate a RESTful request + path mapping with a service. Multiple attributes can be applied to + each request DTO, to map multiple paths to the service. + + + + + Initializes an instance of the class. + + + The path template to map to the request. See + RouteAttribute.Path + for details on the correct format. + + + + + Initializes an instance of the class. + + + The path template to map to the request. See + RouteAttribute.Path + for details on the correct format. + + A comma-delimited list of HTTP verbs supported by the + service. If unspecified, all verbs are assumed to be supported. + + + + Gets or sets the path template to be mapped to the request. + + + A value providing the path mapped to + the request. Never . + + + Some examples of valid paths are: + + + "/Inventory" + "/Inventory/{Category}/{ItemId}" + "/Inventory/{ItemPath*}" + + + Variables are specified within "{}" + brackets. Each variable in the path is mapped to the same-named property + on the request DTO. At runtime, ServiceStack will parse the + request URL, extract the variable values, instantiate the request DTO, + and assign the variable values into the corresponding request properties, + prior to passing the request DTO to the service object for processing. + + It is not necessary to specify all request properties as + variables in the path. For unspecified properties, callers may provide + values in the query string. For example: the URL + "http://services/Inventory?Category=Books&ItemId=12345" causes the same + request DTO to be processed as "http://services/Inventory/Books/12345", + provided that the paths "/Inventory" (which supports the first URL) and + "/Inventory/{Category}/{ItemId}" (which supports the second URL) + are both mapped to the request DTO. + + Please note that while it is possible to specify property values + in the query string, it is generally considered to be less RESTful and + less desirable than to specify them as variables in the path. Using the + query string to specify property values may also interfere with HTTP + caching. + + The final variable in the path may contain a "*" suffix + to grab all remaining segments in the path portion of the request URL and assign + them to a single property on the request DTO. + For example, if the path "/Inventory/{ItemPath*}" is mapped to the request DTO, + then the request URL "http://services/Inventory/Books/12345" will result + in a request DTO whose ItemPath property contains "Books/12345". + You may only specify one such variable in the path, and it must be positioned at + the end of the path. + + + + + Gets or sets short summary of what the route does. + + + + + Gets or sets longer text to explain the behaviour of the route. + + + + + Gets or sets a comma-delimited list of HTTP verbs supported by the service, such as + "GET,PUT,POST,DELETE". + + + A providing a comma-delimited list of HTTP verbs supported + by the service, or empty if all verbs are supported. + + + + + Used to rank the precedences of route definitions in reverse routing. + i.e. Priorities below 0 are auto-generated have less precedence. + + + + + Fallback routes have the lowest precedence, i.e. after normal Routes, static files or any matching Catch All Handlers. + + + + + Generic ResponseStatus for when Response Type can't be inferred. + In schemaless formats like JSON, JSV it has the same shape as a typed Response DTO + + + + + A log entry added by the IRequestLogger + + + + + Decorate on Request DTO's to alter the accessibility of a service and its visibility on /metadata pages + + + + + Restrict access and metadata visibility to any of the specified access scenarios + + The restrict access to scenarios. + + + + Restrict access and metadata visibility to any of the specified access scenarios + + The restrict access to scenarios. + + + + Returns the allowed set of scenarios based on the user-specified restrictions + + + + + + + Allow access but hide from metadata to requests from Localhost only + + + + + Allow access but hide from metadata to requests from Localhost and Local Intranet only + + + + + Restrict access and hide from metadata to requests from Localhost and Local Intranet only + + + + + Restrict access and hide from metadata to requests from Localhost only + + + + + Sets a single access restriction + + Restrict Access to. + + + + Restrict access to any of the specified access scenarios + + Access restrictions + + + + Sets a single metadata Visibility restriction + + Restrict metadata Visibility to. + + + + Restrict metadata visibility to any of the specified access scenarios + + Visibility restrictions + + + + Converts from a User intended restriction to a flag with all the allowed attribute flags set, e.g: + + If No Network restrictions were specified all Network access types are allowed, e.g: + restrict EndpointAttributes.None => ... 111 + + If a Network restriction was specified, only it will be allowed, e.g: + restrict EndpointAttributes.LocalSubnet => ... 010 + + The returned Enum will have a flag with all the allowed attributes set + + + + + + + Error information pertaining to a particular named field. + Used for returning multiple field validation errors.s + + + + + Common ResponseStatus class that should be present on all response DTO's + + + + + Initializes a new instance of the class. + + A response status without an errorcode == success + + + + + Initializes a new instance of the class. + + A response status with an errorcode == failure + + + + + Initializes a new instance of the class. + + A response status with an errorcode == failure + + + + + Holds the custom ErrorCode enum if provided in ValidationException + otherwise will hold the name of the Exception type, e.g. typeof(Exception).Name + + A value of non-null means the service encountered an error while processing the request. + + + + + A human friendly error message + + + + + + + + + + For multiple detailed validation errors. + Can hold a specific error message for each named field. + + + + + Write a partial content result + + + + + Whether this HttpResult allows Partial Response + + + + + Sends the specified request. + + The request. + + + + diff --git a/src/Docs/packages/ServiceStack.Text.4.0.11/ServiceStack.Text.4.0.11.nupkg b/src/Docs/packages/ServiceStack.Text.4.0.11/ServiceStack.Text.4.0.11.nupkg new file mode 100644 index 00000000..9ff6da54 Binary files /dev/null and b/src/Docs/packages/ServiceStack.Text.4.0.11/ServiceStack.Text.4.0.11.nupkg differ diff --git a/src/Docs/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.dll b/src/Docs/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.dll new file mode 100644 index 00000000..30eee22c Binary files /dev/null and b/src/Docs/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.dll differ diff --git a/src/Docs/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.xml b/src/Docs/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.xml new file mode 100644 index 00000000..9688d3e1 --- /dev/null +++ b/src/Docs/packages/ServiceStack.Text.4.0.11/lib/net40/ServiceStack.Text.xml @@ -0,0 +1,703 @@ + + + + ServiceStack.Text + + + + + Utils to load types + + + + + Find the type from the name supplied + + [typeName] or [typeName, assemblyName] + + + + + The top-most interface of the given type, if any. + + + + + Find type if it exists + + + + The type if it exists + + + + Populate an object with Example data. + + + + + + + Populates the object with example data. + + + Tracks how deeply nested we are + + + + + If AlwaysUseUtc is set to true then convert all DateTime to UTC. + + + + + + + Repairs an out-of-spec XML date/time string which incorrectly uses a space instead of a 'T' to separate the date from the time. + These string are occasionally generated by SQLite and can cause errors in OrmLite when reading these columns from the DB. + + The XML date/time string to repair + The repaired string. If no repairs were made, the original string is returned. + + + + WCF Json format: /Date(unixts+0000)/ + + + + + + + WCF Json format: /Date(unixts+0000)/ + + + + + + + Get the type(string) constructor if exists + + The type. + + + + + micro optimizations: using flags instead of value.IndexOfAny(EscapeChars) + + + + + + + Class to hold + + + + + + A fast, standards-based, serialization-issue free DateTime serailizer. + + + + + Determines whether this serializer can create the specified type from a string. + + The type. + + true if this instance [can create from string] the specified type; otherwise, false. + + + + + Parses the specified value. + + The value. + + + + + Deserializes from reader. + + The reader. + + + + + Serializes to string. + + The value. + + + + + Serializes to writer. + + The value. + The writer. + + + + Sets which format to use when serializing TimeSpans + + + + + if the is configured + to take advantage of specification, + to support user-friendly serialized formats, ie emitting camelCasing for JSON + and parsing member names and enum values in a case-insensitive manner. + + + + + if the is configured + to support web-friendly serialized formats, ie emitting lowercase_underscore_casing for JSON + + + + + Define how property names are mapped during deserialization + + + + + Gets or sets a value indicating if the framework should throw serialization exceptions + or continue regardless of deserialization errors. If the framework + will throw; otherwise, it will parse as many fields as possible. The default is . + + + + + Gets or sets a value indicating if the framework should always convert to UTC format instead of local time. + + + + + Gets or sets a value indicating if the framework should always assume is in UTC format if Kind is Unspecified. + + + + + Gets or sets whether we should append the Utc offset when we serialize Utc dates. Defaults to no. + Only supported for when the JsConfig.DateHandler == JsonDateHandler.TimestampOffset + + + + + Gets or sets a value indicating if unicode symbols should be serialized as "\uXXXX". + + + + + If set to true, Interface types will be prefered over concrete types when serializing. + + + + + Sets the maximum depth to avoid circular dependencies + + + + + Set this to enable your own type construction provider. + This is helpful for integration with IoC containers where you need to call the container constructor. + Return null if you don't know how to construct the type and the parameterless constructor will be used. + + + + + If set to true, Interface types will be prefered over concrete types when serializing. + + + + + Always emit type info for this type. Takes precedence over ExcludeTypeInfo + + + + + Never emit type info for this type + + + + + if the is configured + to take advantage of specification, + to support user-friendly serialized formats, ie emitting camelCasing for JSON + and parsing member names and enum values in a case-insensitive manner. + + + + + Define custom serialization fn for BCL Structs + + + + + Define custom raw serialization fn + + + + + Define custom serialization hook + + + + + Define custom deserialization fn for BCL Structs + + + + + Define custom raw deserialization fn for objects + + + + + Exclude specific properties of this type from being serialized + + + + + Opt-in flag to set some Value Types to be treated as a Ref Type + + + + + Whether there is a fn (raw or otherwise) + + + + + The property names on target types must match property names in the JSON source + + + + + The property names on target types may not match the property names in the JSON source + + + + + Uses the xsd format like PT15H10M20S + + + + + Uses the standard .net ToString method of the TimeSpan class + + + + + Get JSON string value converted to T + + + + + Get JSON string value + + + + + Get unescaped string value + + + + + Get unescaped string value + + + + + Write JSON Array, Object, bool or number values as raw string + + + + + Get JSON string value + + + + + Creates an instance of a Type from a string value + + + + + Parses the specified value. + + The value. + + + + + Shortcut escape when we're sure value doesn't contain any escaped chars + + + + + + + Given a character as utf32, returns the equivalent string provided that the character + is legal json. + + + + + + + micro optimizations: using flags instead of value.IndexOfAny(EscapeChars) + + + + + + + Implement the serializer using a more static approach + + + + + + Implement the serializer using a more static approach + + + + + + Public Code API to register commercial license for ServiceStack. + + + + + Internal Utilities to verify licensing + + + + + Pretty Thread-Safe cache class from: + http://code.google.com/p/dapper-dot-net/source/browse/Dapper/SqlMapper.cs + + This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), + and strictly append-only; you cannot change existing values. All key matches are on **REFERENCE** + equality. The type is fully thread-safe. + + + + + Represents an individual object, allowing access to members by-name + + + + + Use the target types definition of equality + + + + + Obtain the hash of the target object + + + + + Use the target's definition of a string representation + + + + + Wraps an individual object, allowing by-name access to that instance + + + + + Get or Set the value of a named member for the underlying object + + + + + The object represented by this instance + + + + + Provides by-name member-access to objects of a given type + + + + + Create a new instance of this type + + + + + Provides a type-specific accessor, allowing by-name access for all objects of that type + + The accessor is cached internally; a pre-existing accessor may be returned + + + + Does this type support new instances via a parameterless constructor? + + + + + Get or set the value of a named member on the target instance + + + + + Maps the path of a file in the context of a VS project + + the relative path + the absolute path + Assumes static content is two directories above the /bin/ directory, + eg. in a unit test scenario the assembly would be in /bin/Debug/. + + + + Maps the path of a file in a self-hosted scenario + + the relative path + the absolute path + Assumes static content is copied to /bin/ folder with the assemblies + + + + Maps the path of a file in an Asp.Net hosted scenario + + the relative path + the absolute path + Assumes static content is in the parent folder of the /bin/ directory + + + + Implement the serializer using a more static approach + + + + + + Creates a new instance of type. + First looks at JsConfig.ModelFactory before falling back to CreateInstance + + + + + Creates a new instance of type. + First looks at JsConfig.ModelFactory before falling back to CreateInstance + + + + + Creates a new instance from the default constructor of type + + + + + Add a Property attribute at runtime. + Not threadsafe, should only add attributes on Startup. + + + + + Add a Property attribute at runtime. + Not threadsafe, should only add attributes on Startup. + + + + + @jonskeet: Collection of utility methods which operate on streams. + r285, February 26th 2009: http://www.yoda.arachsys.com/csharp/miscutil/ + + + + + Reads the given stream up to the end, returning the data as a byte + array. + + + + + Reads the given stream up to the end, returning the data as a byte + array, using the given buffer size. + + + + + Reads the given stream up to the end, returning the data as a byte + array, using the given buffer for transferring data. Note that the + current contents of the buffer is ignored, so the buffer needn't + be cleared beforehand. + + + + + Copies all the data from one stream into another. + + + + + Copies all the data from one stream into another, using a buffer + of the given size. + + + + + Copies all the data from one stream into another, using the given + buffer for transferring data. Note that the current contents of + the buffer is ignored, so the buffer needn't be cleared beforehand. + + + + + Reads exactly the given number of bytes from the specified stream. + If the end of the stream is reached before the specified amount + of data is read, an exception is thrown. + + + + + Reads into a buffer, filling it completely. + + + + + Reads exactly the given number of bytes from the specified stream, + into the given buffer, starting at position 0 of the array. + + + + + Reads exactly the given number of bytes from the specified stream, + into the given buffer, starting at position 0 of the array. + + + + + Same as ReadExactly, but without the argument checks. + + + + + Converts from base: 0 - 62 + + The source. + From. + To. + + + + + Skip the encoding process for 'safe strings' + + + + + + + A class to allow the conversion of doubles to string representations of + their exact decimal values. The implementation aims for readability over + efficiency. + + Courtesy of @JonSkeet + http://www.yoda.arachsys.com/csharp/DoubleConverter.cs + + + + + + + + How many digits are *after* the decimal point + + + + + Constructs an arbitrary decimal expansion from the given long. + The long must not be negative. + + + + + Multiplies the current expansion by the given amount, which should + only be 2 or 5. + + + + + Shifts the decimal point; a negative value makes + the decimal expansion bigger (as fewer digits come after the + decimal place) and a positive value makes the decimal + expansion smaller. + + + + + Removes leading/trailing zeroes from the expansion. + + + + + Converts the value to a proper decimal string representation. + + + + + Creates an instance of a Type from a string value + + + + + Determines whether the specified type is convertible from string. + + The type. + + true if the specified type is convertible from string; otherwise, false. + + + + + Parses the specified value. + + The value. + + + + + Parses the specified type. + + The type. + The value. + + + + + Useful extension method to get the Dictionary[string,string] representation of any POCO type. + + + + + + Recursively prints the contents of any POCO object in a human-friendly, readable format + + + + + + Print Dump to Console.WriteLine + + + + + Print string.Format to Console.WriteLine + + + + + Parses the specified value. + + The value. + + + + diff --git a/src/Docs/packages/repositories.config b/src/Docs/packages/repositories.config new file mode 100644 index 00000000..89297ada --- /dev/null +++ b/src/Docs/packages/repositories.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/Docs/redis-admin-ui/redis-admin-ui-overview.md b/src/Docs/redis-admin-ui/redis-admin-ui-overview.md new file mode 100644 index 00000000..9fe4728e --- /dev/null +++ b/src/Docs/redis-admin-ui/redis-admin-ui-overview.md @@ -0,0 +1,21 @@ +[Join the new google group](http://groups.google.com/group/servicestack) or +follow [@demisbellot](http://twitter.com/demisbellot) and [@ServiceStack](http://twitter.com/servicestack) +for twitter updates. + +#ServiceStack Redis Web Services including the Redis Admin UI +Included is a ServiceStack web service layer which provide JSON, XML, JSV and SOAP 1.1/1.2 for all of Redis operations. +Just like the RedisAdminUI this allows you to fully manage your redis-server instance using javascript from a browser. + +##Live Demo +A live demo of the RedisAdminUI can be found here [http://mono.servicestack.net/RedisAdminUI/AjaxClient/](http://mono.servicestack.net/RedisAdminUI/AjaxClient/) + +View the demos live list of the [available web services](http://www.servicestack.net/RedisAdminUI/servicestack/metadata). + + +#Download +[ServiceStack.RedisWebServices/downloads](https://github.com/ServiceStack/ServiceStack.RedisWebServices/downloads) + +##Troubleshooting +Note: if running via XSP you will want to change the 'DefaultRedirectPath' to: + + diff --git a/src/Docs/redis-client/designing-nosql-database.md b/src/Docs/redis-client/designing-nosql-database.md new file mode 100644 index 00000000..28f4c4c0 --- /dev/null +++ b/src/Docs/redis-client/designing-nosql-database.md @@ -0,0 +1,569 @@ +This page illustrates a good solution on how to design a simple Blog application with [Redis](http://code.google.com/p/redis/) using advanced features of +[ServiceStack's C# Redis Client](~/redis-client/redis-client) to provide fast, simple and elegant solutions to real world scenarios. + +#### All Redis Blog application pages + * Designing a NoSQL Database using Redis + * [Painless data migrations using Redis and other schema-less NoSQL datastores](MigrationsUsingSchemalessNoSql) + +# Designing a NoSQL Database using Redis + +Oren Eini from the popular .NET blog http://ayende.com/Blog/, is putting together a +[series of blog posts](http://ayende.com/Blog/archive/2010/04/20/that-no-sql-thing-the-relational-modeling-anti-pattern-in.aspx) explaining how to go about designing a +simple blog application using a NoSQL database. Although he's using his RavenDB as a reference implementation, this example applies equally well to Redis and other +NoSQL variants. Some solutions will vary based on the advanced features of each NoSQL solution but the 'core data models' should remain the same. + +I will try to add my own thoughts on and where possible show how you can use the advanced features in Redis the C# Client to provide simple, fast and effective solutions. +The entire source code for this example is available in its simplest form at: +[BlogPostExample.cs](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/BlogPostExample.cs). +I will be re-factoring this solution in what I consider a 'best practices approach' for large applications where I will shove all Redis access behind a repository +(so the client doesn't know it's even being used) which I will be maintaining at: +[BlogPostBestPractice.cs](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/BestPractice/BlogPostBestPractice.cs) + +## Modeling Entities in a NoSQL Database + +If you've spent a lot of time building solutions with an RDBMS back-end it can be hard to know which part of your schema is due to the problem domain and which part is the result of an implementation constraint trying to map your ideal domain model onto a relational tabular structure. + +My approach before designing any system is to map out the ideal domain model we need to build in order before I reach for an IDE or a db gui schema creator. Unfortunately creating POCO types is just so damn quick in VS.NET/C#/R# that I've ditched the pencil and paper a long time ago and jump right into using C# automatic properties like a kind of light-weight DSL ripping out entities quicker than I can draw crows feet :) + +If you are like me and prefer to design your domain models from POCO types rather than creating RDBMS tables than you're in good shape in implementing a NoSQL solution as the time when you usually morph your pristine domain models into a tabular structure peppering it with Primary and Foreign keys can now saved and put towards a longer lunch break as most of the times you can skip this step entirely. + +The schema-less nature of NoSQL databases means you can pretty much store your domain models as-is. You will still need to identify your distinct entities from your Key Value Objects. A good guide I use to help with this is whether the Model only makes sense in the context its parent and whether it is 'co-owned' or referenced by another entity. This is where we start pulling the domain model apart, basically you just replace the collection of strongly-typed entities to a collection of entity ids. Effectively you can think of this like foreign-keys but at a much higher level as you only pull it apart of the domain model when you want to manage the entities independently of each other, not as dictated by your schema. + +Taking the User model in it's most simplest form. A User has many blogs, now as you may want to view a list of blogs outside the context of a User (e.g. view a list of newly created blogs, most popular blogs for a category, etc). It becomes a good candidate to being promoted a first class entity. + + //Before + public class User + { + public int Id { get; set; } + public string Name { get; set; } + public List Blogs { get; set; } + } + + //After + public class User + { + public int Id { get; set; } + public string Name { get; set; } + public List BlogIds { get; set; } + } + + +With only a running redis-server instance running and the C# client, the full source to persist and retrieve a list of users is only: + + var redis = new RedisClient(); + using (var redisUsers = redisClient.GetTypedClient()) + { + redisUsers.Store(new User { Id = redisUsers.GetNextSequence(), Name = "ayende" }); + redisUsers.Store(new User { Id = redisUsers.GetNextSequence(), Name = "mythz" }); + + var allUsers = redisUsers.GetAll(); + + //Recursively print the values of the POCO + Console.WriteLine(allUsers.Dump()); + } + /*Output + [ + { + Id: 1, + Name: ayende, + BlogIds: [] + }, + { + Id: 2, + Name: mythz, + BlogIds: [] + } + ] + */ + +_Note: [You can also use the generic T.Dump() Extension method yourself](http://www.servicestack.net/mythz_blog/?p=202)._ + +Ayende has outlined a few scenarios that the Blog application should support. + + * Main page: show list of blogs + * Main page: show list of recent posts + * Main page: show list of recent comments + * Main page: show tag cloud for posts + * Main page: show categories + * Post page: show post and all comments + * Post page: add comment to post + * Tag page: show all posts for tag + * Categories page: show all posts for category + +The full source code for the Redis solution for each of these scenarios is [available here](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/BlogPostExample.cs). Although I will go through each solution in a little more detail below. + +### Main page: show list of blogs +Before we can show a list of blogs, we need to add some first. +Here I make effective use of the Redis client's unique sequence that is maintained for each type. + +In identifying my entities I have a general preference for 'automated ids' which are either +sequential integer ids or Guids - if the entities are going to be distributed across multiple data stores. + +Apart from that persisting an object is just a straight forward process of serializing the object graph into a text-serialization format. +By default, the Redis Client uses [Service Stack's JsonSerializer](http://www.servicestack.net/mythz_blog/?p=344) as it's the fastest and JSON Serializer for .NET. + + //Retrieve strongly-typed Redis clients that let's you natively persist POCO's + using (var redisUsers = redisClient.GetTypedClient()) + using (var redisBlogs = redisClient.GetTypedClient()) + { + //Create the user, getting a unique User Id from the User sequence. + var mythz = new User { Id = redisUsers.GetNextSequence(), Name = "Demis Bellot" }; + + //create some blogs using unique Ids from the Blog sequence. Also adding references + var mythzBlogs = new List + { + new Blog + { + Id = redisBlogs.GetNextSequence(), + UserId = mythz.Id, + UserName = mythz.Name, + Tags = new List { "Architecture", ".NET", "Redis" }, + }, + new Blog + { + Id = redisBlogs.GetNextSequence(), + UserId = mythz.Id, + UserName = mythz.Name, + Tags = new List { "Music", "Twitter", "Life" }, + }, + }; + //Add the blog references + mythzBlogs.ForEach(x => mythz.BlogIds.Add(x.Id)); + + //Store the user and their blogs + redisUsers.Store(mythz); + redisBlogs.StoreAll(mythzBlogs); + + //retrieve all blogs + var blogs = redisBlogs.GetAll(); + + Console.WriteLine(blogs.Dump()); + } + /*Output + [ + { + Id: 1, + UserId: 1, + UserName: Demis Bellot, + Tags: + [ + Architecture, + .NET, + Redis + ], + BlogPostIds: [] + }, + { + Id: 2, + UserId: 1, + UserName: Demis Bellot, + Tags: + [ + Music, + Twitter, + Life + ], + BlogPostIds: [] + } + ] + */ + + +### Main page: show list of recent posts +### Main page: show list of recent comments + +For this scenario we can take advantage of Redis's LTRIM'ing operation to maintain custom rolling lists. +The richness of [Redis list operations](http://code.google.com/p/redis/wiki/RpushCommand) also allow us to prepend or append at either end of the list which we take advantage of in this example. + + + //Get strongly-typed clients + using (var redisBlogPosts = redisClient.GetTypedClient()) + using (var redisComments = redisClient.GetTypedClient()) + { + //To keep this example let's pretend this is a new list of blog posts + var newIncomingBlogPosts = redisBlogPosts.GetAll(); + + //Let's get back an IList wrapper around a Redis server-side List. + var recentPosts = redisBlogPosts.Lists["urn:BlogPost:RecentPosts"]; + var recentComments = redisComments.Lists["urn:BlogPostComment:RecentComments"]; + + foreach (var newBlogPost in newIncomingBlogPosts) + { + //Prepend the new blog posts to the start of the 'RecentPosts' list + recentPosts.Prepend(newBlogPost); + + //Prepend all the new blog post comments to the start of the 'RecentComments' list + newBlogPost.Comments.ForEach(recentComments.Prepend); + } + + //Make this a Rolling list by only keep the latest 3 posts and comments + recentPosts.Trim(0, 2); + recentComments.Trim(0, 2); + + //Print out the last 3 posts: + Console.WriteLine(recentPosts.GetAll().Dump()); + /* Output: + [ + { + Id: 2, + BlogId: 2, + Title: Redis, + Categories: + [ + NoSQL, + Cache + ], + Tags: + [ + Redis, + NoSQL, + Scalability, + Performance + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T22:14:02.755878Z + } + ] + }, + { + Id: 1, + BlogId: 1, + Title: RavenDB, + Categories: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + Raven, + NoSQL, + JSON, + .NET + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T22:14:02.755878Z + }, + { + Content: Second Comment!, + CreatedDate: 2010-04-20T22:14:02.755878Z + } + ] + }, + { + Id: 4, + BlogId: 2, + Title: Couch Db, + Categories: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + CouchDb, + NoSQL, + JSON + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T22:14:02.755878Z + } + ] + } + ] + */ + + Console.WriteLine(recentComments.GetAll().Dump()); + /* Output: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T20:32:42.2970956Z + }, + { + Content: First Comment!, + CreatedDate: 2010-04-20T20:32:42.2970956Z + }, + { + Content: First Comment!, + CreatedDate: 2010-04-20T20:32:42.2970956Z + } + ] + */ + } + + +### Main page: show tag cloud for posts + +Redis Sorted Sets provide the perfect data structure to maintain a Tag cloud of all tags. +It's very fast, elegant structure which provides custom-specific operations to maintain and sort the data. + + + //Get strongly-typed clients + using (var redisBlogPosts = redisClient.GetTypedClient()) + { + var newIncomingBlogPosts = redisBlogPosts.GetAll(); + + foreach (var newBlogPost in newIncomingBlogPosts) + { + //For every tag in each new blog post, increment the number of times each Tag has occurred + newBlogPost.Tags.ForEach(x => + redisClient.IncrementItemInSortedSet("urn:TagCloud", x, 1)); + } + + //Show top 5 most popular tags with their scores + var tagCloud = redisClient.GetRangeWithScoresFromSortedSetDesc("urn:TagCloud", 0, 4); + Console.WriteLine(tagCloud.Dump()); + } + /* Output: + [ + [ + NoSQL, + 4 + ], + [ + Scalability, + 2 + ], + [ + JSON, + 2 + ], + [ + Redis, + 1 + ], + [ + Raven, + 1 + ], + ] + */ + + +### Main page: show categories + +To keep a unique list of categories the right structure to use is a Set. +This allows you to freely add a value multiple times and there will never be any +duplicates as only one of each value is stored. + + + using (var redisBlogPosts = redisClient.GetTypedClient()) + { + var blogPosts = redisBlogPosts.GetAll(); + + foreach (var blogPost in blogPosts) + { + blogPost.Categories.ForEach(x => + redisClient.AddToSet("urn:Categories", x)); + } + + var uniqueCategories = redisClient.GetAllFromSet("urn:Categories"); + Console.WriteLine(uniqueCategories.Dump()); + /* Output: + [ + DocumentDB, + NoSQL, + Cluster, + Cache + ] + */ + } + + +### Post page: show post and all comments + +There is nothing special to do here since comments are Key Value Objects they are +stored and retrieved with the post, so retrieving the post retrieves it's comments as well. + + var postId = 1; + using (var redisBlogPosts = redisClient.GetTypedClient()) + { + var selectedBlogPost = redisBlogPosts.GetById(postId.ToString()); + + Console.WriteLine(selectedBlogPost.Dump()); + /* Output: + { + Id: 1, + BlogId: 1, + Title: RavenDB, + Categories: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + Raven, + NoSQL, + JSON, + .NET + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T21:26:31.9918236Z + }, + { + Content: Second Comment!, + CreatedDate: 2010-04-20T21:26:31.9918236Z + } + ] + } + */ + } + + +### Post page: add comment to post + +Modifying an entity are one of the strengths of a schema-less data store. +Adding a comment is as simple as + * retrieving it's parent post + * modifying the POCO entity in memory by adding a comment to the existing list + * then saving the entity. + + + var postId = 1; + using (var redisBlogPosts = redisClient.GetTypedClient()) + { + var blogPost = redisBlogPosts.GetById(postId.ToString()); + blogPost.Comments.Add( + new BlogPostComment { Content = "Third Post!", CreatedDate = DateTime.UtcNow }); + redisBlogPosts.Store(blogPost); + + var refreshBlogPost = redisBlogPosts.GetById(postId.ToString()); + Console.WriteLine(refreshBlogPost.Dump()); + /* Output: + { + Id: 1, + BlogId: 1, + Title: RavenDB, + Categories: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + Raven, + NoSQL, + JSON, + .NET + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T21:32:39.9688707Z + }, + { + Content: Second Comment!, + CreatedDate: 2010-04-20T21:32:39.9688707Z + }, + { + Content: Third Post!, + CreatedDate: 2010-04-20T21:32:40.2688879Z + } + ] + } + */ + } + + +### Tag page: show all posts for tag + +Basically in order to view all the posts for a particular category we'll need to provide +a reverse-index by adding all matching post ids into a 'Category > Post Id' Set. + +From there it's just a matter of performing a batch request fetching all the Posts with the supplied Ids: + + + using (var redisBlogPosts = redisClient.GetTypedClient()) + { + var newIncomingBlogPosts = redisBlogPosts.GetAll(); + + foreach (var newBlogPost in newIncomingBlogPosts) + { + //For each post add it's Id into each of it's 'Cateogry > Posts' index + newBlogPost.Categories.ForEach(x => + redisClient.AddToSet("urn:Category:" + x, newBlogPost.Id.ToString())); + } + + //Retrieve all the post ids for the category you want to view + var documentDbPostIds = redisClient.GetAllFromSet("urn:Category:DocumentDB"); + + //Make a batch call to retrieve all the posts containing the matching ids + //(i.e. the DocumentDB Category posts) + var documentDbPosts = redisBlogPosts.GetByIds(documentDbPostIds); + + Console.WriteLine(documentDbPosts.Dump()); + /* Output: + [ + { + Id: 4, + BlogId: 2, + Title: Couch Db, + Categories: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + CouchDb, + NoSQL, + JSON + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T21:38:24.6305842Z + } + ] + }, + { + Id: 1, + BlogId: 1, + Title: RavenDB, + Categories: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + Raven, + NoSQL, + JSON, + .NET + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-20T21:38:24.6295842Z + }, + { + Content: Second Comment!, + CreatedDate: 2010-04-20T21:38:24.6295842Z + } + ] + } + ] + */ + } + + + +_This document is a work in progres..._ diff --git a/src/Docs/redis-client/distributed-locking-with-redis.md b/src/Docs/redis-client/distributed-locking-with-redis.md new file mode 100644 index 00000000..7f37febb --- /dev/null +++ b/src/Docs/redis-client/distributed-locking-with-redis.md @@ -0,0 +1,128 @@ +This page shows how to use the [ServiceStack's C# Redis Client](~/redis-client/redis-client) to take advantage of Redis's fast atomic server operations to enable high-performance *distributed locks* that can span across multiple app servers. + +# Achieving High Performance, Distributed Locking with Redis + +When you have a high-performance, scalable network data structure server like Redis accessible to your back end systems, a whole range of technical possibilities open up that we're previously difficult to achieve. Something like multi-server-wide application-level locks were previously only achievable using dedicated, centralized infrastructure and the crafting of some carefully custom concurrent programming logic. + +With Redis this becomes a trivial task as you get simplified access to rich atomic server operations that complete within a fraction of a millisecond. So the same normally CPU-intensive load generated by distributed locking when using a remote file system or RDBMS is barely noticeable on a Redis server. + +[ServiceStack's C# Redis Client](~/redis-client/redis-client) takes advantage of the convenience and safety offered by .NET's IDisposable interface and Redis's +[SetNX operation](http://code.google.com/p/redis/wiki/SetnxCommand) to provide a simple API to implement your own *custom distributed locks*, ensuring at all times that only +1 client at a time can execute the protected logic. While one of the Redis clients obtains the lock, the other clients enter into an 'exponential retry back-off multiplier state' +continually retrying to obtain the lock at random intervals until they are finally successful. + +## Simple API Usage +The locking functionality is available on the [IRedisClient](IRedisClient) and [IRedisTypedClient](IRedisTypedClient) interfaces, the relevant portion of which is displayed below. + + public interface IRedisClient + { + ... + IDisposable AcquireLock(string key); + IDisposable AcquireLock(string key, TimeSpan timeOut); + } + + +_NOTE: The above implementation does not include the ability to auto-recover from a crashed client, power or network failure, so under rare conditions it is possible for all clients to be deadlocked indefinitely waiting on a lock that is never released. In these cases it's wise to supply a `TimeOut` or manually recover from 'zombie locks' by clearing them all on server restarts, etc._ + +Below are a couple examples showing how to use the API in some typical usage scenarios. The full runnable source code of the following examples are +[available here](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/SimpleLocks.cs). + +## Example: Multiple clients acquiring the same lock + +The example below shows the behavior of running 5 concurrent clients trying to acquire the same lock at the same time. +An artificial delay is added inside the lock to simulate a cpu-intensive workload. + + + //The number of concurrent clients to run + const int noOfClients = 5; + var asyncResults = new List(noOfClients); + for (var i = 1; i <= noOfClients; i++) + { + var clientNo = i; + var actionFn = (Action)delegate + { + var redisClient = new RedisClient(TestConfig.SingleHost); + using (redisClient.AcquireLock("testlock")) + { + Console.WriteLine("client {0} acquired lock", clientNo); + var counter = redisClient.Get("atomic-counter"); + + //Add an artificial delay to demonstrate locking behaviour + Thread.Sleep(100); + + redisClient.Set("atomic-counter", counter + 1); + Console.WriteLine("client {0} released lock", clientNo); + } + }; + + //Asynchronously invoke the above delegate in a background thread + asyncResults.Add(actionFn.BeginInvoke(null, null)); + } + + //Wait at most 1 second for all the threads to complete + asyncResults.WaitAll(TimeSpan.FromSeconds(1)); + + //Print out the 'atomic-counter' result + using (var redisClient = new RedisClient(TestConfig.SingleHost)) + { + var counter = redisClient.Get("atomic-counter"); + Console.WriteLine("atomic-counter after 1sec: {0}", counter); + } + + /*Output: + client 1 acquired lock + client 1 released lock + client 3 acquired lock + client 3 released lock + client 4 acquired lock + client 4 released lock + client 5 acquired lock + client 5 released lock + client 2 acquired lock + client 2 released lock + atomic-counter after 1sec: 5 + */ + + +When you acquire a lock without specifying a `TimeOut` as seen in the above example, each waiting client goes into an indefinite loop retrying to acquire the lock until its successful. +If by some chance you had some rogue code not following convention and implementing logic within the disposable scope or worse short circuiting execution using `Thread.Abort`, +you could potentially run into a deadlock situation. This is why it is generally a good idea to specify a `TimeOut` whenever you make a blocking call. So like all good blocking API's +the client lets you specify an optional `TimeOut` parameter as seen in the following example: + +## Example: Acquiring a lock with Time Out + + var redisClient = new RedisClient(TestConfig.SingleHost); + + //Initialize and set counter to '1' + redisClient.Increment("atomic-counter"); + + //Acquire lock and never release it + redisClient.AcquireLock("testlock"); + + var waitFor = TimeSpan.FromSeconds(2); + var now = DateTime.Now; + + try + { + using (var newClient = new RedisClient(TestConfig.SingleHost)) + { + //Attempt to acquire a lock with a 2 second timeout + using (newClient.AcquireLock("testlock", waitFor)) + { + //If lock was acquired this would be incremented to '2' + redisClient.Increment("atomic-counter"); + } + } + } + catch (TimeoutException tex) + { + var timeTaken = DateTime.Now - now; + Console.WriteLine("After '{0}', Received TimeoutException: '{1}'", timeTaken, tex.Message); + + var counter = redisClient.Get("atomic-counter"); + Console.WriteLine("atomic-counter remains at '{0}'", counter); + } + /*Output: + After '00:00:02.3321334', Received TimeoutException: 'Exceeded timeout of 00:00:02' + atomic-counter remains at '1' + */ diff --git a/src/Docs/redis-client/iredisclient-api.md b/src/Docs/redis-client/iredisclient-api.md new file mode 100644 index 00000000..21275536 --- /dev/null +++ b/src/Docs/redis-client/iredisclient-api.md @@ -0,0 +1,234 @@ +Details of the IRedisClient API implemented by the [ServiceStack.Redis client](~/redis-client/redis-client) + +# Introduction + +This is a friendly, more descriptive API implemented by the [ServiceStack.Redis client](~/redis-client/redis-client) +that provides access to key values as strings (or collection of strings for Redis lists and sets). + +Use this API if you just need to access values as strings or you want to have control over your own text serialization format. + +# IRedisClient API + + public interface IRedisClient + : IBasicPersistenceProvider, ICacheClient + { + //Basic Redis Connection operations + int Db { get; set; } + int DbSize { get; } + Dictionary Info { get; } + DateTime LastSave { get; } + string Host { get; } + int Port { get; } + int RetryTimeout { get; set; } + int RetryCount { get; set; } + int SendTimeout { get; set; } + string Password { get; set; } + bool HadExceptions { get; } + + void Save(); + void SaveAsync(); + void Shutdown(); + void RewriteAppendOnlyFileAsync(); + void FlushDb(); + + //Basic Redis Connection Info + string this[string key] { get; set; } + + List GetAllKeys(); + void SetEntry(string key, string value); + void SetEntry(string key, string value, TimeSpan expireIn); + bool SetEntryIfNotExists(string key, string value); + string GetValue(string key); + string GetAndSetEntry(string key, string value); + List GetValues(List keys); + List GetValues(List keys); + int AppendToValue(string key, string value); + string GetSubstring(string key, int fromIndex, int toIndex); + + bool ContainsKey(string key); + bool RemoveEntry(params string[] args); + int IncrementValue(string key); + int IncrementValueBy(string key, int count); + int DecrementValue(string key); + int DecrementValueBy(string key, int count); + List SearchKeys(string pattern); + + RedisKeyType GetEntryType(string key); + string GetRandomKey(); + bool ExpireEntryIn(string key, TimeSpan expireIn); + bool ExpireEntryAt(string key, DateTime expireAt); + TimeSpan GetTimeToLive(string key); + List GetSortedEntryValues(string key, int startingFrom, int endingAt); + + //Useful high-level abstractions + IRedisTypedClient GetTypedClient(); + + IHasNamed Lists { get; set; } + IHasNamed Sets { get; set; } + IHasNamed SortedSets { get; set; } + IHasNamed Hashes { get; set; } + + IRedisTransaction CreateTransaction(); + + IDisposable AcquireLock(string key); + IDisposable AcquireLock(string key, TimeSpan timeOut); + + #region Redis pubsub + + IRedisSubscription CreateSubscription(); + void PublishMessage(string toChannel, string message); + + #endregion + + + #region Set operations + + HashSet GetAllItemsFromSet(string setId); + void AddItemToSet(string setId, string item); + void RemoveItemFromSet(string setId, string item); + string PopItemFromSet(string setId); + void MoveBetweenSets(string fromSetId, string toSetId, string item); + int GetSetCount(string setId); + bool SetContainsItem(string setId, string item); + HashSet GetIntersectFromSets(params string[] setIds); + void StoreIntersectFromSets(string intoSetId, params string[] setIds); + HashSet GetUnionFromSets(params string[] setIds); + void StoreUnionFromSets(string intoSetId, params string[] setIds); + HashSet GetDifferencesFromSet(string fromSetId, params string[] withSetIds); + void StoreDifferencesFromSet(string intoSetId, string fromSetId, params string[] withSetIds); + string GetRandomItemFromSet(string setId); + + #endregion + + + #region List operations + + List GetAllItemsFromList(string listId); + List GetRangeFromList(string listId, int startingFrom, int endingAt); + List GetRangeFromSortedList(string listId, int startingFrom, int endingAt); + void AddItemToList(string listId, string value); + void PrependItemToList(string listId, string value); + void RemoveAllFromList(string listId); + string RemoveStartFromList(string listId); + string BlockingRemoveStartFromList(string listId, TimeSpan? timeOut); + string RemoveEndFromList(string listId); + void TrimList(string listId, int keepStartingFrom, int keepEndingAt); + int RemoveItemFromList(string listId, string value); + int RemoveItemFromList(string listId, string value, int noOfMatches); + int GetListCount(string listId); + string GetItemFromList(string listId, int listIndex); + void SetItemInList(string listId, int listIndex, string value); + + //Queue operations + void EnqueueItemOnList(string listId, string value); + string DequeueItemFromList(string listId); + string BlockingDequeueItemFromList(string listId, TimeSpan? timeOut); + + //Stack operations + void PushItemToList(string listId, string value); + string PopItemFromList(string listId); + string BlockingPopItemFromList(string listId, TimeSpan? timeOut); + string PopAndPushItemBetweenLists(string fromListId, string toListId); + + #endregion + + + #region Sorted Set operations + + bool AddItemToSortedSet(string setId, string value); + bool AddItemToSortedSet(string setId, string value, double score); + bool RemoveItemFromSortedSet(string setId, string value); + string PopItemWithLowestScoreFromSortedSet(string setId); + string PopItemWithHighestScoreFromSortedSet(string setId); + bool SortedSetContainsItem(string setId, string value); + double IncrementItemInSortedSet(string setId, string value, double incrementBy); + int GetItemIndexInSortedSet(string setId, string value); + int GetItemIndexInSortedSetDesc(string setId, string value); + List GetAllItemsFromSortedSet(string setId); + List GetAllItemsFromSortedSetDesc(string setId); + List GetRangeFromSortedSet(string setId, int fromRank, int toRank); + List GetRangeFromSortedSetDesc(string setId, int fromRank, int toRank); + IDictionary GetAllWithScoresFromSortedSet(string setId); + IDictionary GetRangeWithScoresFromSortedSet(string setId, int fromRank, int toRank); + IDictionary GetRangeWithScoresFromSortedSetDesc(string setId, int fromRank, int toRank); + List GetRangeFromSortedSetByLowestScore(string setId, string fromStringScore, string toStringScore); + List GetRangeFromSortedSetByLowestScore(string setId, string fromStringScore, string toStringScore, int? skip, int? take); + List GetRangeFromSortedSetByLowestScore(string setId, double fromScore, double toScore); + List GetRangeFromSortedSetByLowestScore(string setId, double fromScore, double toScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(string setId, string fromStringScore, string toStringScore); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(string setId, string fromStringScore, string toStringScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(string setId, double fromScore, double toScore); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(string setId, double fromScore, double toScore, int? skip, int? take); + List GetRangeFromSortedSetByHighestScore(string setId, string fromStringScore, string toStringScore); + List GetRangeFromSortedSetByHighestScore(string setId, string fromStringScore, string toStringScore, int? skip, int? take); + List GetRangeFromSortedSetByHighestScore(string setId, double fromScore, double toScore); + List GetRangeFromSortedSetByHighestScore(string setId, double fromScore, double toScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(string setId, string fromStringScore, string toStringScore); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(string setId, string fromStringScore, string toStringScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(string setId, double fromScore, double toScore); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(string setId, double fromScore, double toScore, int? skip, int? take); + int RemoveRangeFromSortedSet(string setId, int minRank, int maxRank); + int RemoveRangeFromSortedSetByScore(string setId, double fromScore, double toScore); + int GetSortedSetCount(string setId); + double GetItemScoreInSortedSet(string setId, string value); + int StoreIntersectFromSortedSets(string intoSetId, params string[] setIds); + int StoreUnionFromSortedSets(string intoSetId, params string[] setIds); + + #endregion + + + #region Hash operations + + bool HashContainsEntry(string hashId, string key); + bool SetEntryInHash(string hashId, string key, string value); + bool SetEntryInHashIfNotExists(string hashId, string key, string value); + void SetRangeInHash(string hashId, IEnumerable> keyValuePairs); + int IncrementValueInHash(string hashId, string key, int incrementBy); + string GetValueFromHash(string hashId, string key); + List GetValuesFromHash(string hashId, params string[] keys); + bool RemoveEntryFromHash(string hashId, string key); + int GetHashCount(string hashId); + List GetHashKeys(string hashId); + List GetHashValues(string hashId); + Dictionary GetAllEntriesFromHash(string hashId); + + #endregion + } + + +# IBasicPersistenceProvider API +This is a common interface shared by all other ServiceStack persistence providers (OrmLite, db4o, Memchached, In Memory and File System cache providers, etc). + +It provides generic operations to get, store and delete any C# POCO type. + + public interface IBasicPersistenceProvider : IDisposable + { + T GetById(object id) + where T : class, new(); + + IList GetByIds(ICollection ids) + where T : class, new(); + + T Store(T entity) + where T : class, new(); + + void StoreAll(IEnumerable entities) + where TEntity : class, new(); + + void Delete(T entity) + where T : class, new(); + + void DeleteById(object id) + where T : class, new(); + + void DeleteByIds(ICollection ids) + where T : class, new(); + + void DeleteAll() + where TEntity : class, new(); + } + + +Generally, if you only have basic persistence needs I would recommend developing against the above common data access API as it is easier for +other persistence providers to implement and increases the likely hood that your existing library can be reused as-is to have your POCO types +persist against other data stores i.e. against an RDBMS with OrmLite, etc. diff --git a/src/Docs/redis-client/iredisnativeclient-api.md b/src/Docs/redis-client/iredisnativeclient-api.md new file mode 100644 index 00000000..9069679d --- /dev/null +++ b/src/Docs/redis-client/iredisnativeclient-api.md @@ -0,0 +1,122 @@ +## A C# client that provides a low-level raw bytes API access to Redis + +This is a low-level API implemented by the [ServiceStack.Redis](~/redis-client/redis-client) client that provides raw byte access to a Redis server. +Each method maps to 1:1 to a [Redis operation](http://code.google.com/p/redis/wiki/CommandReference) of the same name. + +### IRedisNativeClient Interface + + public interface IRedisNativeClient + : IDisposable + { + //Redis utility operations + Dictionary Info { get; } + int Db { get; set; } + void Save(); + void BgSave(); + void Shutdown(); + void BgRewriteAof(); + void Quit(); + void FlushDb(); + void FlushAll(); + bool Ping(); + string Echo(string text); + void SlaveOf(string hostname, int port); + void SlaveOfNoOne(); + + //Common key-value Redis operations + void Set(string key, byte[] value); + void SetEx(string key, int expireInSeconds, byte[] value); + int SetNX(string key, byte[] value); + byte[] Get(string key); + byte[] GetSet(string key, byte[] value); + int Del(string key); + int Incr(string key); + int IncrBy(string key, int count); + int Decr(string key); + int DecrBy(string key, int count); + int Append(string key, byte[] value); + byte[] Substr(string key, int fromIndex, int toIndex); + + string RandomKey(); + void Rename(string oldKeyname, string newKeyname); + int Expire(string key, int seconds); + int ExpireAt(string key, long unixTime); + int Ttl(string key); + + //Redis Sort operation (works on lists, sets or hashes) + byte[][] Sort(string listOrSetId, SortOptions sortOptions); + + //Redis List operations + byte[][] LRange(string listId, int startingFrom, int endingAt); + void RPush(string listId, byte[] value); + void LPush(string listId, byte[] value); + void LTrim(string listId, int keepStartingFrom, int keepEndingAt); + int LRem(string listId, int removeNoOfMatches, byte[] value); + int LLen(string listId); + byte[] LIndex(string listId, int listIndex); + void LSet(string listId, int listIndex, byte[] value); + byte[] LPop(string listId); + byte[] RPop(string listId); + byte[][] BLPop(string listId, int timeOutSecs); + byte[][] BRPop(string listId, int timeOutSecs); + byte[] RPopLPush(string fromListId, string toListId); + + + //Redis Set operations + byte[][] SMembers(string setId); + void SAdd(string setId, byte[] value); + void SRem(string setId, byte[] value); + byte[] SPop(string setId); + void SMove(string fromSetId, string toSetId, byte[] value); + int SCard(string setId); + int SIsMember(string setId, byte[] value); + byte[][] SInter(params string[] setIds); + void SInterStore(string intoSetId, params string[] setIds); + byte[][] SUnion(params string[] setIds); + void SUnionStore(string intoSetId, params string[] setIds); + byte[][] SDiff(string fromSetId, params string[] withSetIds); + void SDiffStore(string intoSetId, string fromSetId, params string[] withSetIds); + byte[] SRandMember(string setId); + + + //Redis Sorted Set operations + int ZAdd(string setId, double score, byte[] value); + int ZRem(string setId, byte[] value); + double ZIncrBy(string setId, double incrBy, byte[] value); + int ZRank(string setId, byte[] value); + int ZRevRank(string setId, byte[] value); + byte[][] ZRange(string setId, int min, int max); + byte[][] ZRangeWithScores(string setId, int min, int max); + byte[][] ZRevRange(string setId, int min, int max); + byte[][] ZRevRangeWithScores(string setId, int min, int max); + byte[][] ZRangeByScore(string setId, double min, double max, int? skip, int? take); + byte[][] ZRangeByScoreWithScores(string setId, double min, double max, int? skip, int? take); + byte[][] ZRevRangeByScore(string setId, double min, double max, int? skip, int? take); + byte[][] ZRevRangeByScoreWithScores(string setId, double min, double max, int? skip, int? take); + int ZRemRangeByRank(string setId, int min, int max); + int ZRemRangeByScore(string setId, double fromScore, double toScore); + int ZCard(string setId); + double ZScore(string setId, byte[] value); + int ZUnionStore(string intoSetId, params string[] setIds); + int ZInterStore(string intoSetId, params string[] setIds); + + //Redis Hash operations + int HSet(string hashId, byte[] key, byte[] value); + int HSetNX(string hashId, byte[] key, byte[] value); + void HMSet(string hashId, byte[][] keys, byte[][] values); + int HIncrby(string hashId, byte[] key, int incrementBy); + byte[] HGet(string hashId, byte[] key); + int HDel(string hashId, byte[] key); + int HExists(string hashId, byte[] key); + int HLen(string hashId); + byte[][] HKeys(string hashId); + byte[][] HVals(string hashId); + byte[][] HGetAll(string hashId); + + //Redis Pub/Sub operations + void Publish(string toChannel, byte[] message); + byte[][] Subscribe(params string[] toChannels); + byte[][] UnSubscribe(params string[] toChannels); + byte[][] PSubscribe(params string[] toChannelsMatchingPatterns); + byte[][] PUnSubscribe(params string[] toChannelsMatchingPatterns); + } diff --git a/src/Docs/redis-client/iredistransaction-api.md b/src/Docs/redis-client/iredistransaction-api.md new file mode 100644 index 00000000..3ba3123e --- /dev/null +++ b/src/Docs/redis-client/iredistransaction-api.md @@ -0,0 +1,66 @@ +The [Redis Transactions](~/redis-client/redis-transactions) interface implemented by [ServiceStack's C# Redis Client](~/redis-client/redis-client). + +# Introduction + +Redis transaction interface provides useful overloads that let you Queue-up any [IRedisTypedClient] operation within a single transaction. +The API provides support for a callback so you also have access to any return values returned as part of the transaction as well. + +# Usage + +Below is a simple example showing how to access, use and commit the transaction. + + var typedClient = Redis.GetTypedClient(); + using (var trans = typedClient.CreateTransaction()) + { + trans.QueueCommand(r => r.Set("nosqldbs", new MyPocoType {Id = 1, Name = "Redis")); + + trans.Commit(); + } + + +For a transaction that operates on string values see [IRedisTransaction]. + +# Details + + public interface IRedisTypedTransaction + : IDisposable + { + void QueueCommand(Action> command); + void QueueCommand(Action> command, Action onSuccessCallback); + void QueueCommand(Action> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, int> command); + void QueueCommand(Func, int> command, Action onSuccessCallback); + void QueueCommand(Func, int> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, bool> command); + void QueueCommand(Func, bool> command, Action onSuccessCallback); + void QueueCommand(Func, bool> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, double> command); + void QueueCommand(Func, double> command, Action onSuccessCallback); + void QueueCommand(Func, double> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, byte[]> command); + void QueueCommand(Func, byte[]> command, Action onSuccessCallback); + void QueueCommand(Func, byte[]> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, string> command); + void QueueCommand(Func, string> command, Action onSuccessCallback); + void QueueCommand(Func, string> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, T> command); + void QueueCommand(Func, T> command, Action onSuccessCallback); + void QueueCommand(Func, T> command, Action onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, List> command); + void QueueCommand(Func, List> command, Action> onSuccessCallback); + void QueueCommand(Func, List> command, Action> onSuccessCallback, Action onErrorCallback); + + void QueueCommand(Func, List> command); + void QueueCommand(Func, List> command, Action> onSuccessCallback); + void QueueCommand(Func, List> command, Action> onSuccessCallback, Action onErrorCallback); + + void Commit(); + void Rollback(); + } diff --git a/src/Docs/redis-client/iredistypedclient-api.md b/src/Docs/redis-client/iredistypedclient-api.md new file mode 100644 index 00000000..0def2194 --- /dev/null +++ b/src/Docs/redis-client/iredistypedclient-api.md @@ -0,0 +1,187 @@ + +A 'strongly-typed' API available on [Service Stack's C# Redis Client](~/redis-client/redis-client) to make all Redis Value operations to apply against any c# type + +# Strongly typed Generic Client API + +Below is the strongly-typed API that you have access to after you call `IRedisClient.GetTypedClient()` e.g.: + + using (var redisClient = new RedisClient()) + { + var redis = redisClient.GetTypedClient(); + } + +The redis variable now holds a strongly-typed generic client that allows Redis value operations to apply against `MyPocoType`. +The interface below lists all available operations: + + public interface IRedisTypedClient + : IBasicPersistenceProvider + { + IHasNamed> Lists { get; set; } + IHasNamed> Sets { get; set; } + IHasNamed> SortedSets { get; set; } + IRedisHash GetHash(string hashId); + + IRedisTypedTransaction CreateTransaction(); + + IDisposable AcquireLock(); + IDisposable AcquireLock(TimeSpan timeOut); + + int Db { get; set; } + List GetAllKeys(); + + T this[string key] { get; set; } + + string SequenceKey { get; set; } + void SetSequence(int value); + int GetNextSequence(); + RedisKeyType GetEntryType(string key); + string GetRandomKey(); + + void SetEntry(string key, T value); + void SetEntry(string key, T value, TimeSpan expireIn); + bool SetEntryIfNotExists(string key, T value); + T GetValue(string key); + T GetAndSetValue(string key, T value); + bool ContainsKey(string key); + bool RemoveEntry(string key); + bool RemoveEntry(params string[] args); + bool RemoveEntry(params IHasStringId[] entities); + int IncrementValue(string key); + int IncrementValueBy(string key, int count); + int DecrementValue(string key); + int DecrementValueBy(string key, int count); + bool ExpireEntryIn(string key, TimeSpan expiresAt); + bool ExpireEntryAt(string key, DateTime dateTime); + TimeSpan GetTimeToLive(string key); + void Save(); + void SaveAsync(); + void FlushDb(); + void FlushAll(); + T[] SearchKeys(string pattern); + List GetValues(List keys); + List GetSortedEntryValues(IRedisSet fromSet, int startingFrom, int endingAt); + + HashSet GetAllItemsFromSet(IRedisSet fromSet); + void AddItemToSet(IRedisSet toSet, T item); + void RemoveItemFromSet(IRedisSet fromSet, T item); + T PopItemFromSet(IRedisSet fromSet); + void MoveBetweenSets(IRedisSet fromSet, IRedisSet toSet, T item); + int GetSetCount(IRedisSet set); + bool SetContainsItem(IRedisSet set, T item); + HashSet GetIntersectFromSets(params IRedisSet[] sets); + void StoreIntersectFromSets(IRedisSet intoSet, params IRedisSet[] sets); + HashSet GetUnionFromSets(params IRedisSet[] sets); + void StoreUnionFromSets(IRedisSet intoSet, params IRedisSet[] sets); + HashSet GetDifferencesFromSet(IRedisSet fromSet, params IRedisSet[] withSets); + void StoreDifferencesFromSet(IRedisSet intoSet, IRedisSet fromSet, params IRedisSet[] withSets); + T GetRandomItemFromSet(IRedisSet fromSet); + + List GetAllItemsFromList(IRedisList fromList); + List GetRangeFromList(IRedisList fromList, int startingFrom, int endingAt); + List SortList(IRedisList fromList, int startingFrom, int endingAt); + void AddItemToList(IRedisList fromList, T value); + void PrependItemToList(IRedisList fromList, T value); + T RemoveStartFromList(IRedisList fromList); + T BlockingRemoveStartFromList(IRedisList fromList, TimeSpan? timeOut); + T RemoveEndFromList(IRedisList fromList); + void RemoveAllFromList(IRedisList fromList); + void TrimList(IRedisList fromList, int keepStartingFrom, int keepEndingAt); + int RemoveItemFromList(IRedisList fromList, T value); + int RemoveItemFromList(IRedisList fromList, T value, int noOfMatches); + int GetListCount(IRedisList fromList); + T GetItemFromList(IRedisList fromList, int listIndex); + void SetItemInList(IRedisList toList, int listIndex, T value); + + //Queue operations + void EnqueueItemOnList(IRedisList fromList, T item); + T DequeueItemFromList(IRedisList fromList); + T BlockingDequeueItemFromList(IRedisList fromList, TimeSpan? timeOut); + + //Stack operations + void PushItemToList(IRedisList fromList, T item); + T PopItemFromList(IRedisList fromList); + T BlockingPopItemFromList(IRedisList fromList, TimeSpan? timeOut); + T PopAndPushItemBetweenLists(IRedisList fromList, IRedisList toList); + + void AddItemToSortedSet(IRedisSortedSet toSet, T value); + void AddItemToSortedSet(IRedisSortedSet toSet, T value, double score); + bool RemoveItemFromSortedSet(IRedisSortedSet fromSet, T value); + T PopItemWithLowestScoreFromSortedSet(IRedisSortedSet fromSet); + T PopItemWithHighestScoreFromSortedSet(IRedisSortedSet fromSet); + bool SortedSetContainsItem(IRedisSortedSet set, T value); + double IncrementItemInSortedSet(IRedisSortedSet set, T value, double incrementBy); + int GetItemIndexInSortedSet(IRedisSortedSet set, T value); + int GetItemIndexInSortedSetDesc(IRedisSortedSet set, T value); + List GetAllItemsFromSortedSet(IRedisSortedSet set); + List GetAllItemsFromSortedSetDesc(IRedisSortedSet set); + List GetRangeFromSortedSet(IRedisSortedSet set, int fromRank, int toRank); + List GetRangeFromSortedSetDesc(IRedisSortedSet set, int fromRank, int toRank); + IDictionary GetAllWithScoresFromSortedSet(IRedisSortedSet set); + IDictionary GetRangeWithScoresFromSortedSet(IRedisSortedSet set, int fromRank, int toRank); + IDictionary GetRangeWithScoresFromSortedSetDesc(IRedisSortedSet set, int fromRank, int toRank); + List GetRangeFromSortedSetByLowestScore(IRedisSortedSet set, string fromStringScore, string toStringScore); + List GetRangeFromSortedSetByLowestScore(IRedisSortedSet set, string fromStringScore, string toStringScore, int? skip, int? take); + List GetRangeFromSortedSetByLowestScore(IRedisSortedSet set, double fromScore, double toScore); + List GetRangeFromSortedSetByLowestScore(IRedisSortedSet set, double fromScore, double toScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(IRedisSortedSet set, string fromStringScore, string toStringScore); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(IRedisSortedSet set, string fromStringScore, string toStringScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(IRedisSortedSet set, double fromScore, double toScore); + IDictionary GetRangeWithScoresFromSortedSetByLowestScore(IRedisSortedSet set, double fromScore, double toScore, int? skip, int? take); + List GetRangeFromSortedSetByHighestScore(IRedisSortedSet set, string fromStringScore, string toStringScore); + List GetRangeFromSortedSetByHighestScore(IRedisSortedSet set, string fromStringScore, string toStringScore, int? skip, int? take); + List GetRangeFromSortedSetByHighestScore(IRedisSortedSet set, double fromScore, double toScore); + List GetRangeFromSortedSetByHighestScore(IRedisSortedSet set, double fromScore, double toScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(IRedisSortedSet set, string fromStringScore, string toStringScore); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(IRedisSortedSet set, string fromStringScore, string toStringScore, int? skip, int? take); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(IRedisSortedSet set, double fromScore, double toScore); + IDictionary GetRangeWithScoresFromSortedSetByHighestScore(IRedisSortedSet set, double fromScore, double toScore, int? skip, int? take); + int RemoveRangeFromSortedSet(IRedisSortedSet set, int minRank, int maxRank); + int RemoveRangeFromSortedSetByScore(IRedisSortedSet set, double fromScore, double toScore); + int GetSortedSetCount(IRedisSortedSet set); + double GetItemScoreInSortedSet(IRedisSortedSet set, T value); + int StoreIntersectFromSortedSets(IRedisSortedSet intoSetId, params IRedisSortedSet[] setIds); + int StoreUnionFromSortedSets(IRedisSortedSet intoSetId, params IRedisSortedSet[] setIds); + + bool HashContainsEntry(IRedisHash hash, TKey key); + bool SetEntryInHash(IRedisHash hash, TKey key, T value); + bool SetEntryInHashIfNotExists(IRedisHash hash, TKey key, T value); + void SetRangeInHash(IRedisHash hash, IEnumerable> keyValuePairs); + T GetValueFromHash(IRedisHash hash, TKey key); + bool RemoveEntryFromHash(IRedisHash hash, TKey key); + int GetHashCount(IRedisHash hash); + List GetHashKeys(IRedisHash hash); + List GetHashValues(IRedisHash hash); + Dictionary GetAllEntriesFromHash(IRedisHash hash); + } + + + +# Common data access interface + +Including the above methods, the Generic client also implements Redis non-specific +common data access operations that can be easily implemented by other data persistence providers should you want to swap providers in future. + + public interface IBasicPersistenceProvider + : IDisposable + { + T GetById(string id); + + IList GetByIds(ICollection ids); + + IList GetAll(); + + T Store(T entity); + + void StoreAll(IEnumerable entities); + + void Delete(T entity); + + void DeleteById(string id); + + void DeleteByIds(ICollection ids); + + void DeleteAll(); + } + +Generally, if you only have basic persistence needs I would recommend developing against the above common data access API as it is easier for other +persistence providers to implement and increases the likely hood that your library can be reused as-is to persist against other data stores i.e. against an RDBMS with OrmLite, etc. diff --git a/src/Docs/redis-client/redis-client.md b/src/Docs/redis-client/redis-client.md new file mode 100644 index 00000000..7b3403bd --- /dev/null +++ b/src/Docs/redis-client/redis-client.md @@ -0,0 +1,236 @@ +[Join the new google group](http://groups.google.com/group/servicestack) or +follow [@demisbellot](http://twitter.com/demisbellot) and [@boxerab](http://twitter.com/boxerab) +for twitter updates. + +# An Open Source C# Client for Redis + +[Redis](http://code.google.com/p/redis/) is one of the fastest and feature-rich key-value stores to come from the [NoSQL](http://en.wikipedia.org/wiki/NoSQL) movement. +It is similar to memcached but the dataset is not volatile, and values can either be strings lists, sets, sorted sets or hashes. + +[ServiceStack's C# Redis Client](~/redis-client/redis-client) is an Open Source C# Redis client based on [Miguel de Icaza](http://twitter.com/migueldeicaza) previous efforts with [redis-sharp](http://github.com/migueldeicaza/redis-sharp). + +There are a number of different APIs available which are all a friendly drop-in with your local IOC: +The `ServiceStack.Redis.RedisClient` class below implements the following interfaces: + + * [ICacheClient](~/framework/caching-options) - If you are using Redis solely as a cache, you should bind to the [ServiceStack's common interface](~/framework/caching-options) as there already are In-Memory an Memcached implementations available in ServiceStack, allowing you to easily switch providers in-future. + * [IRedisNativeClient](~/redis-client/iredisnativeclient-api) - For those wanting a low-level raw byte access (where you can control your own serialization/deserialization) that map 1:1 with Redis operations of the same name. + +For most cases if you require access to Redis-specific functionality you would want to bind to the interface below: + + * [IRedisClient](~/redis-client/iredisclient-api) - Provides a friendlier, more descriptive API that lets you store values as strings (UTF8 encoding). + * [IRedisTypedClient](~/redis-client/iredistypedclient-api) - created with `IRedisClient.GetTypedClient()` - it returns a 'strongly-typed client' that provides a typed-interface for all redis value operations that works against any C#/.NET POCO type. + +The class hierarchy for the C# Redis clients effectively look like: + + RedisTypedClient (POCO) > RedisClient (string) > RedisNativeClient (raw byte[]) + +Each client is optimized for maximum efficiency and provides layered functionality for maximum developer productivity: + + * The RedisNativeClient exposes raw **byte[]** apis and does no marshalling and passes all values directly to redis. + * The RedisClient assumes **string** values and simply converts strings to UTF8 bytes before sending to Redis + * The RedisTypedClient provides a generic interface allowing you to add POCO values. The POCO types are serialized using [.NETs fastest JSON Serializer](http://www.servicestack.net/mythz_blog/?p=344) which is then converted to UTF8 bytes and sent to Redis. + +At all times you can pick the most optimal Redis Client for your needs so you can achieve maximum efficiency in your applications. + +### Redis Client API Overview +[![Redis Client API](http://mono.servicestack.net/img/Redis-annotated-preview.png)](http://mono.servicestack.net/img/Redis-annotated.png) + +### Thread-safe client managers +For multi-threaded applications you can choose from our different client connection managers: + + * BasicRedisClientManager - a load-balance (master-write and read-slaves) client manager that returns a new [IRedisClient](~/redis-client/iredisclient-api) connection with the defaults specified (faster when accessing a redis-server instance on the same host). + * PooledRedisClientManager - a load-balanced (master-write and read-slaves) client manager that utilizes a pool of redis client connections (faster when accessing a redis-server instance over the network). + +# Download + +You can download the Redis Client in any one of the following ways: + +* Packaged by default in [ServiceStack.dll](https://github.com/ServiceStack/ServiceStack/downloads) +* Available to download separately as a stand-alone [ServiceStack.Redis.dll](https://github.com/ServiceStack/ServiceStack.Redis/downloads) +* As Source Code via Git: `git clone git://github.com/ServiceStack/ServiceStack.Redis.git` +* For those interested in having a GUI admin tool to visualize your Redis data should check out the [Redis Admin UI](http://www.servicestack.net/mythz_blog/?p=381) + +[View the release notes](https://github.com/ServiceStack/ServiceStack.Redis/wiki/Redis-Client-Release-Notes). + +### Redis Server builds for Windows + + * [Downloads for Cygwin 32bit Redis Server Windows builds](http://code.google.com/p/servicestack/wiki/RedisWindowsDownload). + * [Project that lets you run Redis as a Windows Service](https://github.com/rgl/redis) + * [Downloads for MinGW 32bit and 64bit Redis Server Windows builds](http://github.com/dmajkic/redis/downloads) + + +# Getting Started with the C# Redis client + +###[C# Redis Client wiki](~/redis-client/redis-overview) +Contains all the examples, tutorials and resources you need to get you up to speed with common operations and the latest features. + +[Useful Links on Redis server](~/redis-client/useful-redis-links) + +### Specific Examples + * [Using Transactions in Redis (i.e. MULTI/EXEC/DISCARD)](~/redis-client/redis-transactions) + * [Using Redis's built-in Publsih/Subscribe pattern for high performance network notifications](~/redis-client/redis-pubsub) + * [Using Redis to create high performance *distributed locks* spannable across multiple app servers](https://github.com/ServiceStack/ServiceStack.Redis/wiki/RedisLocks) + +# Simple example using Redis Lists + +Below is a simple example to give you a flavour of how easy it is to use some of Redis's advanced data structures - in this case Redis Lists: +_Full source code of this example is [viewable online](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/ShippersExample.cs)_ + + using (var redisClient = new RedisClient()) + { + //Create a 'strongly-typed' API that makes all Redis Value operations to apply against Shippers + IRedisTypedClient redis = redisClient.GetTypedClient(); + + //Redis lists implement IList while Redis sets implement ICollection + var currentShippers = redis.Lists["urn:shippers:current"]; + var prospectiveShippers = redis.Lists["urn:shippers:prospective"]; + + currentShippers.Add( + new Shipper { + Id = redis.GetNextSequence(), + CompanyName = "Trains R Us", + DateCreated = DateTime.UtcNow, + ShipperType = ShipperType.Trains, + UniqueRef = Guid.NewGuid() + }); + + currentShippers.Add( + new Shipper { + Id = redis.GetNextSequence(), + CompanyName = "Planes R Us", + DateCreated = DateTime.UtcNow, + ShipperType = ShipperType.Planes, + UniqueRef = Guid.NewGuid() + }); + + var lameShipper = new Shipper { + Id = redis.GetNextSequence(), + CompanyName = "We do everything!", + DateCreated = DateTime.UtcNow, + ShipperType = ShipperType.All, + UniqueRef = Guid.NewGuid() + }; + + currentShippers.Add(lameShipper); + + Dump("ADDED 3 SHIPPERS:", currentShippers); + + currentShippers.Remove(lameShipper); + + Dump("REMOVED 1:", currentShippers); + + prospectiveShippers.Add( + new Shipper { + Id = redis.GetNextSequence(), + CompanyName = "Trucks R Us", + DateCreated = DateTime.UtcNow, + ShipperType = ShipperType.Automobiles, + UniqueRef = Guid.NewGuid() + }); + + Dump("ADDED A PROSPECTIVE SHIPPER:", prospectiveShippers); + + redis.PopAndPushBetweenLists(prospectiveShippers, currentShippers); + + Dump("CURRENT SHIPPERS AFTER POP n' PUSH:", currentShippers); + Dump("PROSPECTIVE SHIPPERS AFTER POP n' PUSH:", prospectiveShippers); + + var poppedShipper = redis.PopFromList(currentShippers); + Dump("POPPED a SHIPPER:", poppedShipper); + Dump("CURRENT SHIPPERS AFTER POP:", currentShippers); + + //reset sequence and delete all lists + redis.SetSequence(0); + redis.Remove(currentShippers, prospectiveShippers); + Dump("DELETING CURRENT AND PROSPECTIVE SHIPPERS:", currentShippers); + } + + /* + == EXAMPLE OUTPUT == + + ADDED 3 SHIPPERS: + Id:1,CompanyName:Trains R Us,ShipperType:Trains,DateCreated:2010-01-31T11:53:37.7169323Z,UniqueRef:d17c5db0415b44b2ac5da7b6ebd780f5 + Id:2,CompanyName:Planes R Us,ShipperType:Planes,DateCreated:2010-01-31T11:53:37.799937Z,UniqueRef:e02a73191f4b4e7a9c44eef5b5965d06 + Id:3,CompanyName:We do everything!,ShipperType:All,DateCreated:2010-01-31T11:53:37.8009371Z,UniqueRef:d0c249bbbaf84da39fc4afde1b34e332 + + REMOVED 1: + Id:1,CompanyName:Trains R Us,ShipperType:Trains,DateCreated:2010-01-31T11:53:37.7169323Z,UniqueRef:d17c5db0415b44b2ac5da7b6ebd780f5 + Id:2,CompanyName:Planes R Us,ShipperType:Planes,DateCreated:2010-01-31T11:53:37.799937Z,UniqueRef:e02a73191f4b4e7a9c44eef5b5965d06 + + ADDED A PROSPECTIVE SHIPPER: + Id:4,CompanyName:Trucks R Us,ShipperType:Automobiles,DateCreated:2010-01-31T11:53:37.8539401Z,UniqueRef:67d7d4947ebc4b0ba5c4d42f5d903bec + + CURRENT SHIPPERS AFTER POP n' PUSH: + Id:4,CompanyName:Trucks R Us,ShipperType:Automobiles,DateCreated:2010-01-31T11:53:37.8539401Z,UniqueRef:67d7d4947ebc4b0ba5c4d42f5d903bec + Id:1,CompanyName:Trains R Us,ShipperType:Trains,DateCreated:2010-01-31T11:53:37.7169323Z,UniqueRef:d17c5db0415b44b2ac5da7b6ebd780f5 + Id:2,CompanyName:Planes R Us,ShipperType:Planes,DateCreated:2010-01-31T11:53:37.799937Z,UniqueRef:e02a73191f4b4e7a9c44eef5b5965d06 + + PROSPECTIVE SHIPPERS AFTER POP n' PUSH: + + POPPED a SHIPPER: + Id:2,CompanyName:Planes R Us,ShipperType:Planes,DateCreated:2010-01-31T11:53:37.799937Z,UniqueRef:e02a73191f4b4e7a9c44eef5b5965d06 + + CURRENT SHIPPERS AFTER POP: + Id:4,CompanyName:Trucks R Us,ShipperType:Automobiles,DateCreated:2010-01-31T11:53:37.8539401Z,UniqueRef:67d7d4947ebc4b0ba5c4d42f5d903bec + Id:1,CompanyName:Trains R Us,ShipperType:Trains,DateCreated:2010-01-31T11:53:37.7169323Z,UniqueRef:d17c5db0415b44b2ac5da7b6ebd780f5 + + DELETING CURRENT AND PROSPECTIVE SHIPPERS: + */ + +More examples are available in the [RedisExamples Redis examples page] and in the comprehensive +[test suite](https://github.com/ServiceStack/ServiceStack.Redis/tree/master/tests/ServiceStack.Redis.Tests) + + +## Speed +One of the best things about Redis is the speed - it is quick. + +[This example](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/RedisClientTests.cs) +below stores and gets the entire [Northwind database](http://code.google.com/p/servicestack/source/browse/trunk/Common/Northwind.Benchmarks/Northwind.Common/DataModel/NorthwindData.cs) (3202 records) in less *1.2 secs* - we've never had it so quick! + +_(Running inside a VS.NET/R# unit test on a 3 year old iMac)_ + + using (var client = new RedisClient()) + { + var before = DateTime.Now; + client.StoreAll(NorthwindData.Categories); + client.StoreAll(NorthwindData.Customers); + client.StoreAll(NorthwindData.Employees); + client.StoreAll(NorthwindData.Shippers); + client.StoreAll(NorthwindData.Orders); + client.StoreAll(NorthwindData.Products); + client.StoreAll(NorthwindData.OrderDetails); + client.StoreAll(NorthwindData.CustomerCustomerDemos); + client.StoreAll(NorthwindData.Regions); + client.StoreAll(NorthwindData.Territories); + client.StoreAll(NorthwindData.EmployeeTerritories); + + Console.WriteLine("Took {0}ms to store the entire Northwind database ({1} records)", + (DateTime.Now - before).TotalMilliseconds, totalRecords); + + + before = DateTime.Now; + var categories = client.GetAll(); + var customers = client.GetAll(); + var employees = client.GetAll(); + var shippers = client.GetAll(); + var orders = client.GetAll(); + var products = client.GetAll(); + var orderDetails = client.GetAll(); + var customerCustomerDemos = client.GetAll(); + var regions = client.GetAll(); + var territories = client.GetAll(); + var employeeTerritories = client.GetAll(); + + Console.WriteLine("Took {0}ms to get the entire Northwind database ({1} records)", + (DateTime.Now - before).TotalMilliseconds, totalRecords); + } + /* + == EXAMPLE OUTPUT == + + Took 1020.0583ms to store the entire Northwind database (3202 records) + Took 132.0076ms to get the entire Northwind database (3202 records) + */ + + +Note: The total time taken includes an extra Redis operation for each record to store the id in a Redis set for each +type as well as serializing and de-serializing each record using Service Stack's TypeSerializer. \ No newline at end of file diff --git a/src/Docs/redis-client/redis-overview.md b/src/Docs/redis-client/redis-overview.md new file mode 100644 index 00000000..2dbe54fb --- /dev/null +++ b/src/Docs/redis-client/redis-overview.md @@ -0,0 +1,52 @@ +# Welcome to the ServiceStack.Redis C# Client wiki! + +This index hopes to provide a good starting page to find information about the [ServiceStack's Open Source C# Redis Client](~/redis-client/redis-client). + +The Redis Client runs on Windows with .NET and Linux with [Mono](http://www.mono-project.com). +Included as part of ServiceStack is: + +* [IRedisNativeClient](~/redis-client/iredisnativeclient-api) -A low-level API that provides raw byte access to a Redis server. Each method maps to 1:1 to a Redis operation of the same name. +* **[IRedisClient](~/redis-client/iredisclient-api)** - A friendly, more descriptive API implemented by the ServiceStack.Redis client that provides access to key values as strings (or collection of strings for Redis lists and sets). +* **[IRedisTypedClient](~/redis-client/iredistypedclient-api)** - A high-level 'strongly-typed' API available on Service Stack's C# Redis Client to make all Redis Value operations to apply against any c# type. Where all complex types are transparently serialized to JSON using [ServiceStack JsonSerializer](~/text-serializers/json-csv-jsv-serializers) - [The fastest JSON Serializer for .NET](http://www.servicestack.net/mythz_blog/?p=344). +* Thread-safe `BasicRedisClientManager` and `PooledRedisClientManager` connection pooling implementations which plugs nicely in your local IOC and is useful when talking to Redis inside an ASP.NET application or Windows Service. + +# Download + +Links the the latest packages are [available on the home page](~/redis-client/redis-client). +Alternatively view all releases on the [projects downloads page](https://github.com/ServiceStack/ServiceStack.Redis/downloads). + +## Getting Started + +If you are new to Redis (or NoSQL in general) I recommend the following resources: + +* [Useful Links about Redis](~/redis-client/useful-redis-links) +* [Designing a Simple Blog application with Redis](~/redis-client/designing-nosql-database) + - To get a flavour of how to use the C# Client view the [above example source code](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/BlogPostExample.cs) as well as the re-factored, [Best Practices / Repository approach here](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/BestPractice/BlogPostBestPractice.cs). +* [Painless data migrations with schema-less NoSQL datastores and Redis](~/redis-client/schemaless-nosql-migrations) - Which demonstrates how flexible and resilient the JsonSerializer is with the Schema-less solution used with Redis. + +## Redis Admin UI + +Spawned from deep within the fires of Unix, for the longest time the only interface access to your Redis DataStore was through the highly-functional but still command-line only **redis-cli** command line utility. + +Also developed in conjunction with the C# Redis Client, to help with visualizing your data in Redis is the [Redis Admin UI](http://www.servicestack.net/mythz_blog/?p=381). It was specifically designed to take advantages of the conventions of the C# Redis Client to provide a fast, functional view into your data. Like all of ServiceStack it runs on .NET and Mono with the [public demo hosted on CentOS/Nginx/Mono](http://www.servicestack.net/RedisAdminUI/AjaxClient/). + +The download and source code for the Redis Admin UI is maintained in the [ServiceStack.RedisWebServices project](~/redis-admin-ui/redis-admin-ui-overview). + +## Ajax Web Services for Redis + +The Redis Admin UI is actually a pure Ajax web application (i.e. a pure static JavaScript file). In order to be able to develop an Ajax application that talks to Redis (which is a highly optimized, binary-safe tcp protocol) we must make the Redis operations available via Ajax Web Services. Which happens to be exactly what the [ServiceStack.RedisWebServices](~/redis-admin-ui/redis-admin-ui-overview) does. It takes advantage of ServiceStack to provide XML, JSON, JSV, SOAP 1.1/1.2 for all of Redis operations. A [list of all the operations available](http://www.servicestack.net/RedisAdminUI/Public/Metadata) can be seen on the public demo. + +Effectively [ServiceStack.RedisWebServices](~/redis-admin-ui/redis-admin-ui-overview) gives Redis CouchDB-like powers where the Ajax Web Services layer allows websites to talk directly to Redis without any custom middle-tier just like the Redis Admin UI :) + +# Advanced C# Redis Client features + +After you have familiarized yourself with the basics of the Redis Client here are a few useful resources to explore the Advanced features and capabilities of Redis: + +* How to create [Transactions / Atomic Operations](~/redis-client/redis-transactions) with Redis using the [IRedisTransaction](~/redis-client/iredistransaction-api) and [IRedisTypedTransaction](https://github.com/ServiceStack/ServiceStack.Redis/wiki/IRedisTypedTransaction) APIs +* [Fast, efficient distributed locking with Redis](https://github.com/ServiceStack/ServiceStack.Redis/wiki/RedisLocks) +* [Pub/Sub Messaging with Redis](~/redis-client/redis-pubsub) + + + + + diff --git a/src/Docs/redis-client/redis-pubsub.md b/src/Docs/redis-client/redis-pubsub.md new file mode 100644 index 00000000..ec34811b --- /dev/null +++ b/src/Docs/redis-client/redis-pubsub.md @@ -0,0 +1,215 @@ +This page shows how to use [ServiceStack's C# Redis Client](~/redis-client/redis-client) to take advantage of the Publish/Subscribe messaging paradigm built into +[Redis](http://code.google.com/p/redis/) to be able to develop high-performance network notification servers. + +# Publish/Subscribe messaging pattern in Redis +Redis is largely recognized as the most efficient NoSQL solution to manage rich data structures, providing the data source to power stateless back-end app servers. What a lot of people don't know is that it also has a number of characteristics that also make it a prime candidate to develop high-performance networking solutions with. Probably its most noteworthy feature in this area to date, is its built-in Publishing / Subscribe / Messaging support which enables a new range of elegant comet-based and high performance networking solutions to be developed. + +Under the covers this is achieved with the [PUBLISH/SUBSCRIBE redis server operations](http://code.google.com/p/redis/wiki/PublishSubscribe). +Essentially these operations allows any number of clients to be able to *Listen* on any arbitrary named channel. As soon as an external client *Publishes* a message to that channel, +each *listening* client is notified. The clients will continue to receive messages as long as they maintain at least one *active subscription*. + +Service Stack's C# Client exposes this functionality in a similar way as the [redis-rb Ruby client](http://github.com/ezmobius/redis-rb/blob/master/examples/pubsub.rb). +Essentially you create a *Subscription*, Then *Register* your handlers on each of the events you're interested in, then it's just a matter of *Subscribing* to the channels you're interested in. +When you want your consumers to stop receiving messages you need to *unsubscribe* from all channels. + +# Pub/Sub Examples + +Below are some examples showing how to use the API to accomplish some basic tasks. At the end of each example is the Console output showing the sequence of events helping you visualize the order +of each operation. The full runnable source code for these examples are +[available here](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/SimplePubSub.cs). + +## Example 1 - Publish and receive 5 messages + + var messagesReceived = 0; + + using (var redisConsumer = new RedisClient(TestConfig.SingleHost)) + using (var subscription = redisConsumer.CreateSubscription()) + { + subscription.OnSubscribe = channel => + { + Console.WriteLine("Subscribed to '{0}'", channel); + }; + subscription.OnUnSubscribe = channel => + { + Console.WriteLine("UnSubscribed from '{0}'", channel); + }; + subscription.OnMessage = (channel, msg) => + { + Console.WriteLine("Received '{0}' from channel '{1}'", msg, channel); + + //As soon as we've received all 5 messages, disconnect by unsubscribing to all channels + if (++messagesReceived == PublishMessageCount) + { + subscription.UnSubscribeFromAllChannels(); + } + }; + + ThreadPool.QueueUserWorkItem(x => + { + Thread.Sleep(200); + Console.WriteLine("Begin publishing messages..."); + + using (var redisPublisher = new RedisClient(TestConfig.SingleHost)) + { + for (var i = 1; i <= PublishMessageCount; i++) + { + var message = MessagePrefix + i; + Console.WriteLine("Publishing '{0}' to '{1}'", message, ChannelName); + redisPublisher.PublishMessage(ChannelName, message); + } + } + }); + + Console.WriteLine("Started Listening On '{0}'", ChannelName); + subscription.SubscribeToChannels(ChannelName); //blocking + } + + Console.WriteLine("EOF"); + + /*Output: + Started Listening On 'CHANNEL' + Subscribed to 'CHANNEL' + Begin publishing messages... + Publishing 'MESSAGE 1' to 'CHANNEL' + Received 'MESSAGE 1' from channel 'CHANNEL' + Publishing 'MESSAGE 2' to 'CHANNEL' + Received 'MESSAGE 2' from channel 'CHANNEL' + Publishing 'MESSAGE 3' to 'CHANNEL' + Received 'MESSAGE 3' from channel 'CHANNEL' + Publishing 'MESSAGE 4' to 'CHANNEL' + Received 'MESSAGE 4' from channel 'CHANNEL' + Publishing 'MESSAGE 5' to 'CHANNEL' + Received 'MESSAGE 5' from channel 'CHANNEL' + UnSubscribed from 'CHANNEL' + EOF + */ + + +## Example 2 - Publish 5 messages to 3 different clients + + + const int noOfClients = 3; + + for (var i = 1; i <= noOfClients; i++) + { + var clientNo = i; + ThreadPool.QueueUserWorkItem(x => + { + using (var redisConsumer = new RedisClient(TestConfig.SingleHost)) + using (var subscription = redisConsumer.CreateSubscription()) + { + var messagesReceived = 0; + subscription.OnSubscribe = channel => + { + Console.WriteLine("Client #{0} Subscribed to '{1}'", clientNo, channel); + }; + subscription.OnUnSubscribe = channel => + { + Console.WriteLine("Client #{0} UnSubscribed from '{1}'", clientNo, channel); + }; + subscription.OnMessage = (channel, msg) => + { + Console.WriteLine("Client #{0} Received '{1}' from channel '{2}'", + clientNo, msg, channel); + + if (++messagesReceived == PublishMessageCount) + { + subscription.UnSubscribeFromAllChannels(); + } + }; + + Console.WriteLine("Client #{0} started Listening On '{1}'", clientNo, ChannelName); + subscription.SubscribeToChannels(ChannelName); //blocking + } + + Console.WriteLine("Client #{0} EOF", clientNo); + }); + } + + using (var redisClient = new RedisClient(TestConfig.SingleHost)) + { + Thread.Sleep(500); + Console.WriteLine("Begin publishing messages..."); + + for (var i = 1; i <= PublishMessageCount; i++) + { + var message = MessagePrefix + i; + Console.WriteLine("Publishing '{0}' to '{1}'", message, ChannelName); + redisClient.PublishMessage(ChannelName, message); + } + } + + Thread.Sleep(500); + + /*Output: + Client #1 started Listening On 'CHANNEL' + Client #2 started Listening On 'CHANNEL' + Client #1 Subscribed to 'CHANNEL' + Client #2 Subscribed to 'CHANNEL' + Client #3 started Listening On 'CHANNEL' + Client #3 Subscribed to 'CHANNEL' + Begin publishing messages... + Publishing 'MESSAGE 1' to 'CHANNEL' + Client #1 Received 'MESSAGE 1' from channel 'CHANNEL' + Client #2 Received 'MESSAGE 1' from channel 'CHANNEL' + Publishing 'MESSAGE 2' to 'CHANNEL' + Client #1 Received 'MESSAGE 2' from channel 'CHANNEL' + Client #2 Received 'MESSAGE 2' from channel 'CHANNEL' + Publishing 'MESSAGE 3' to 'CHANNEL' + Client #3 Received 'MESSAGE 1' from channel 'CHANNEL' + Client #3 Received 'MESSAGE 2' from channel 'CHANNEL' + Client #3 Received 'MESSAGE 3' from channel 'CHANNEL' + Client #1 Received 'MESSAGE 3' from channel 'CHANNEL' + Client #2 Received 'MESSAGE 3' from channel 'CHANNEL' + Publishing 'MESSAGE 4' to 'CHANNEL' + Client #1 Received 'MESSAGE 4' from channel 'CHANNEL' + Client #3 Received 'MESSAGE 4' from channel 'CHANNEL' + Publishing 'MESSAGE 5' to 'CHANNEL' + Client #1 Received 'MESSAGE 5' from channel 'CHANNEL' + Client #3 Received 'MESSAGE 5' from channel 'CHANNEL' + Client #1 UnSubscribed from 'CHANNEL' + Client #1 EOF + Client #3 UnSubscribed from 'CHANNEL' + Client #3 EOF + Client #2 Received 'MESSAGE 4' from channel 'CHANNEL' + Client #2 Received 'MESSAGE 5' from channel 'CHANNEL' + Client #2 UnSubscribed from 'CHANNEL' + Client #2 EOF + */ + + + +# Pub/Sub API + + + public interface IRedisSubscription + : IDisposable + { + // The number of active subscriptions this client has + int SubscriptionCount { get; } + + // Registered handler called after client *Subscribes* to each new channel + Action OnSubscribe { get; set; } + + // Registered handler called when each message is received + Action OnMessage { get; set; } + + // Registered handler called when each channel is unsubscribed + Action OnUnSubscribe { get; set; } + + // Subscribe to channels by name + void SubscribeToChannels(params string[] channels); + + // Subscribe to channels matching the supplied patterns + void SubscribeToChannelsMatching(params string[] patterns); + + void UnSubscribeFromAllChannels(); + void UnSubscribeFromChannels(params string[] channels); + void UnSubscribeFromChannelsMatching(params string[] patterns); + } + + +## Find out more + +For more information on the capabilities of the Publish/Subscribe API check out the +[PubSub unit tests](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/RedisPubSubTests.cs). diff --git a/src/Docs/redis-client/redis-release-notes.md b/src/Docs/redis-client/redis-release-notes.md new file mode 100644 index 00000000..d2a5ac03 --- /dev/null +++ b/src/Docs/redis-client/redis-release-notes.md @@ -0,0 +1,95 @@ +Latest release notes for the latest version of the c# [ServiceStack.Redis](~/redis-client/redis-client). + +# Redis Client v1.30 Release Notes +This version adds support for the recently released [Redis v2.0](http://code.google.com/p/redis/wiki/Redis_2_0_0_Changelog). +This release also fixes a major performance issue with the older clients so it is now a recommended upgrade for all older clients which ideally should coincide with an upgrade to redis-server v2.0. + +## Warning: Breaking API Changes +Unfortunately during development of [Redis Web Services](http://www.servicestack.net/RedisWebServices.Host/Public/Metadata) I became aware that the nomenclature +of the descriptive API found in the [IRedisClient] and [IRedisTypedClient] were sometimes in-consistent. Normally when making changes to published API's I would +continue to deprecate and support the older API's unfortunately since there was _so many_ changes supporting both API's would've made it more confusing so I've +taken the opportunity with the release of redis-server v2.0 to start with a fresh slate, though I will continue to make available the older version (v1.20) of the client below. + +### The new terminology used in the new API +The wording in the new [IRedisClient] and [RedisWebService](http://www.servicestack.net/RedisWebServices.Host/Public/Metadata) API's: + * For write operations I specify to *what* I'm adding an as well as *where* I'm adding it to: + * e.g. `AddItemToList` as opposed to `AddToList`. + * For read operations I specify *what* I'm getting and *where* I'm getting it from + * e.g. `GetAllItemsFromList` as opposed to `GetAllFromList`. + * A normal Key/Value pair using Get/Set/SetEntryInHash is referred to as an `Entry` which contains both a 'Key' and a 'Value'. So the normal `Set` becomes `SetEntry` + * A Value in a List, Set, or SortedSet is referred as an `Item` + +Please file any issues you find with the C# Client (or the rest of ServiceStack) on the [issues pages](https://github.com/ServiceStack/ServiceStack.Redis/issues). + +# Download +The latest version of the open source c# redis client is available: + * As a stand-alone dll - https://github.com/downloads/mythz/ServiceStack.Redis/ServiceStack.Redis.zip + * Or bundled inside the core Service Stack binaries - https://github.com/downloads/mythz/ServiceStack/ServiceStack.zip + +Download the stable and development release of the Redis Server Windows builds here: +http://code.google.com/p/servicestack/wiki/RedisWindowsDownload (currently v2.0RC) + +## Older Releases +For those that can't move to the new redis-server and new C# client, I will maintain the downloads of the older v2.0 libraries: + * [ServiceStack.Redis-1.20.zip](http://servicestack.googlecode.com/files/ServiceStack.Redis-1.20.zip) + * [ServiceStack-1.20.zip](http://servicestack.googlecode.com/files/ServiceStack-1.20.zip) + + + +# Redis Client v1.20 Release Notes +This version adds support for *all operations* available in Redis v1.3.11 (and the upcoming v2.0 RC) apart from the special debug commands: MONITOR / CONFIG / DEBUG +which are commonly accessed via redis-cli/telnet for diagnosing a live-running Redis instance. + +# Redis Client v1.19 Release Notes +The biggest feature of this release is support for Redis Publish/Subscribe operations. +Other than that all client client API's now use the new binary safe Redis wire protocol so now all arguments including keys are binary safe strings. +Most new Redis operations available in the latest version of redis-server v1.3.10 have been implemented. + +Other noteworthy mentions: + * *AcquireLock* with built in backoff-sleep-multiplier was added on both [IRedisClient] and [IRedisTypedClient] to provide an elegant way to achieve application level locks. + * The Refactoring process to change all commands to use the new protocol added more tests which discovered and fixed more bugs. + * Issues identified in some hash commands resulted in more tests and fixes. -- thanks for reporting + +New or changed API methods: + * *[RedisPubSub Publish/Subscribe/PSubscribe/UnSubscribe/PUnSubscribe]* added to support Redis Pub/Sub + * *Append* / *Substring* string operations requiring v1.3.10 redis-server + * *SetString* with TimeOut now uses the more efficient *SetEx* operation + * *GetAllWithScoresFromSortedSet* + * *Sort* has been overhauled to allow for simpler opt-in usage. + += Redis Client v1.14 Release Notes = +This release brings the client up to date with v1.3.9 of the redis-server with the following new operations included: + * [HINCRBY](http://code.google.com/p/redis/wiki/HincrbyCommand) + * [HMSET](http://code.google.com/p/redis/wiki/HmsetCommand) + * [HSETNX](http://code.google.com/p/redis/wiki/HsetnxCommand) (only available in redis trunk) +You can access these new operations with the IRedisClient using the v1.3.9 of the redis-server. + +Richer Transaction support has been improved with the addition of the [IRedisTypedTransaction IRedisTypedTransaction] which utilizes the +[IRedisTypedClient](~/redis-client/iredistypedclient-api) +to provide transactions against strongly-typed POCO types. Examples can be found on the test page +[RedisTypedTransactionTests.cs](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Generic/RedisTypedTransactionTests.cs) + +# Redis Client v1.09 Release Notes + +## Features +The biggest feature in this release is the addition of Redis Transactions. Almost every command in [IRedisClient] can now be queued and executed as part of an atomic Redis operation. For more info on how to use transactions visit [RedisTransactions]. + +## Other noteworthy features + * Fixed some bugs and provided richer support for Redis Hashes including implementing a the .NET native generic `IDictionary` interface. + * Name changes for a couple SortedSet and Hash operations for better consistency and readability. + +# Older Release Notes + +## Redis Client v1.08 Release Notes + +### API compatibility +This version of the client includes support for the *Redis 1.3.7 API*. This includes support for all Sorted Sets and Hash operations. + +### Features + * Included in the release is preliminary support for Transient Redis Message Queues. + * Thread-safe load balanced `PooledRedisClientManager` and `BasicRedisClientManager` client managers, suitable to drop in any IOC. + * Supports configuration of multiple read-write masters and read-only slave Redis server instances. + +### Breaking API changes: + * Due to a change in the Redis 1.3.7 KEYS operation, `IRedisClient.AllKeys` and `IRedisClient.GetKeys()` now return a `List`. + \ No newline at end of file diff --git a/src/Docs/redis-client/redis-transactions.md b/src/Docs/redis-client/redis-transactions.md new file mode 100644 index 00000000..24e1d896 --- /dev/null +++ b/src/Docs/redis-client/redis-transactions.md @@ -0,0 +1,122 @@ +This page provides examples on how to create atomic Redis transactions with [ServiceStackRedis Service Stack's C# Redis Client] + +# How to create custom atomic operations in Redis + +One of the main features of Redis is the ability to construct custom atomic operations. This is achieved by utilizing Redis's +[MULTI/EXEC/DISCARD](http://code.google.com/p/redis/wiki/MultiExecCommand) operations. + +[ServiceStack's C# Redis Client](~/redis-client/redis-client) makes it easy to utilize Redis transactions by providing a strongly-typed [IRedisTransaction](IRedisTransaction) +(for strings) and [IRedisTypedTransaction](IRedisTypedTransaction) (for POCO types) APIs with convenience methods to allow you to combine any [IRedisClient](IRedisClient) operation within a single transaction. + +Creating a transaction is done by calling `IRedisClient.CreateTransaction()`. +From there you 'Queue' up all operations you want to be apart of the transaction by using one of the `IRedisTransaction.QueueCommand()` overloads. After that you can execute all the operations by calling `IRedisTransaction.Commit()` which will send the 'EXEC' command to the Redis server executing all the Queued commands and processing their callbacks. + +If you don't call the `Commit()` before the end of the using block, `Dispose()` method will automatically invokes `Rollback()` that will send the 'DISCARD' command disposing of the current transaction and resetting the Redis client connection back to its previous state. + +## Redis Transaction Examples + +Below is a simple example showing how to queue up Redis operations with and without a callback. + + + int callbackResult; + using (var trans = redis.CreateTransaction()) + { + trans.QueueCommand(r => r.Increment("key")); + trans.QueueCommand(r => r.Increment("key"), i => callbackResult = i); + + trans.Commit(); + } + //The value of "key" is incremented twice. The latest value of which is also stored in 'callbackResult'. + + +### Other common examples +The full-source code and other common examples can be found on the +[common transaction tests page](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/RedisTransactionCommonTests.cs). + + [Test] + public void Can_Set_and_Expire_key_in_atomic_transaction() + { + var oneSec = TimeSpan.FromSeconds(1); + + Assert.That(Redis.GetString("key"), Is.Null); + using (var trans = Redis.CreateTransaction()) //Calls 'MULTI' + { + trans.QueueCommand(r => r.SetString("key", "a")); //Queues 'SET key a' + trans.QueueCommand(r => r.ExpireKeyIn("key", oneSec)); //Queues 'EXPIRE key 1' + + trans.Commit(); //Calls 'EXEC' + + } //Calls 'DISCARD' if 'EXEC' wasn't called + + Assert.That(Redis.GetString("key"), Is.EqualTo("a")); + Thread.Sleep(TimeSpan.FromSeconds(2)); + Assert.That(Redis.GetString("key"), Is.Null); + } + + [Test] + public void Can_Pop_priority_message_from_SortedSet_and_Add_to_workq_in_atomic_transaction() + { + var messages = new List { "message4", "message3", "message2" }; + + Redis.AddToList("workq", "message1"); + + var priority = 1; + messages.ForEach(x => Redis.AddToSortedSet("prioritymsgs", x, priority++)); + + var highestPriorityMessage = Redis.PopFromSortedSetItemWithHighestScore("prioritymsgs"); + + using (var trans = Redis.CreateTransaction()) + { + trans.QueueCommand(r => r.RemoveFromSortedSet("prioritymsgs", highestPriorityMessage)); + trans.QueueCommand(r => r.AddToList("workq", highestPriorityMessage)); + + trans.Commit(); + } + + Assert.That(Redis.GetAllFromList("workq"), + Is.EquivalentTo(new List { "message1", "message2" })); + Assert.That(Redis.GetAllFromSortedSet("prioritymsgs"), + Is.EquivalentTo(new List { "message3", "message4" })); + } + + +## All-in-one example +This and other examples can be found by looking at the +[RedisTransactionTests.cs test suite](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/RedisTransactionTests.cs). + +Here is an all in one examples combining many different Redis operations within a single transaction: + + [Test] + public void Supports_different_operation_types_in_same_transaction() + { + var incrementResults = new List(); + var collectionCounts = new List(); + var containsItem = false; + + Assert.That(Redis.GetString(Key), Is.Null); + using (var trans = Redis.CreateTransaction()) + { + trans.QueueCommand(r => r.Increment(Key), intResult => incrementResults.Add(intResult)); + trans.QueueCommand(r => r.AddToList(ListKey, "listitem1")); + trans.QueueCommand(r => r.AddToList(ListKey, "listitem2")); + trans.QueueCommand(r => r.AddToSet(SetKey, "setitem")); + trans.QueueCommand(r => r.SetContainsValue(SetKey, "setitem"), b => containsItem = b); + trans.QueueCommand(r => r.AddToSortedSet(SortedSetKey, "sortedsetitem1")); + trans.QueueCommand(r => r.AddToSortedSet(SortedSetKey, "sortedsetitem2")); + trans.QueueCommand(r => r.AddToSortedSet(SortedSetKey, "sortedsetitem3")); + trans.QueueCommand(r => r.GetListCount(ListKey), intResult => collectionCounts.Add(intResult)); + trans.QueueCommand(r => r.GetSetCount(SetKey), intResult => collectionCounts.Add(intResult)); + trans.QueueCommand(r => r.GetSortedSetCount(SortedSetKey), intResult => collectionCounts.Add(intResult)); + trans.QueueCommand(r => r.Increment(Key), intResult => incrementResults.Add(intResult)); + + trans.Commit(); + } + + Assert.That(containsItem, Is.True); + Assert.That(Redis.GetString(Key), Is.EqualTo("2")); + Assert.That(incrementResults, Is.EquivalentTo(new List { 1, 2 })); + Assert.That(collectionCounts, Is.EquivalentTo(new List { 2, 1, 3 })); + Assert.That(Redis.GetAllFromList(ListKey), Is.EquivalentTo(new List { "listitem1", "listitem2" })); + Assert.That(Redis.GetAllFromSet(SetKey), Is.EquivalentTo(new List { "setitem" })); + Assert.That(Redis.GetAllFromSortedSet(SortedSetKey), Is.EquivalentTo(new List { "sortedsetitem1", "sortedsetitem2", "sortedsetitem3" })); + } diff --git a/src/Docs/redis-client/schemaless-nosql-migrations.md b/src/Docs/redis-client/schemaless-nosql-migrations.md new file mode 100644 index 00000000..204c006f --- /dev/null +++ b/src/Docs/redis-client/schemaless-nosql-migrations.md @@ -0,0 +1,379 @@ +This page runs through a typical example to show how painless typical data migrations can be when using Redis and other NoSQL schema-less data stores. + +#### All Redis Blog application pages + * [Designing a NoSQL Database using Redis](~/redis-client/designing-nosql-database) + * Painless data migrations using Redis and other schema-less NoSQL datastores + +# Painless data migrations with schema-less NoSQL data stores and Redis + +Developing *new* greenfield database systems utilizing a RDBMS back-end is mostly a trouble-free experience. Before the system is live, you're able to easily modify a schema by nuking the entire application database, and re-creating it with automated DDL scripts that will create and populate it with test data that fits your new schema. + +The real troubles in your IT life happens after your first deployment and your system goes live. At that point you no longer have the option to nuke the database and re-create it from scratch. If you're lucky, you have a script in place that can automatically infer the required DDL statements to migrate from your old schema to your new one. However any significant changes to your schema are likely to involve late nights, downtime, and a non-trivial amount of effort to ensure a successful migration to the new db schema. + +This process is much less painful with schema-less data stores. In fact in most cases when you're just adding and removing fields it doesn't exist at all. By not having your datastore understand intrinsic details of your schema, it means it's no longer an infrastructure-level issue and can easily be handled by application logic if needed. + +Being maintenance-free, schema-less and non-intrusive are fundamental design qualities baked into Redis and its operations. For example querying a list of recent BlogPosts returns the same result for an *empty list* as it would in an *empty Redis database* - 0 results. As values in Redis are binary-safe strings you're able to store anything you want in them and most importantly by extension this means that all Redis operations can support all of your application types without needing an 'intermediate language' like DDL to provide a rigid schema of what to expect. Without any prior initialization your code can talk directly to a Redis datastore naturally as if it was an in-memory collection. + +To illustrate what can be achieved in practice, I will run through two different strategies of handling schema changes. + + * The do-nothing approach - where adding, removing fields and non-destructive change of field types are automatically handled. + * Using a custom translation - using application level logic to customize the translation between the old and new types. + +The full runnable source code for these example are [available here](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/Examples/BestPractice/BlogPostMigrations.cs). + +## Example Code +To demonstrate a typical migration scenario, I'm using the `BlogPost` type defined on the previous page to project it to a fundamentally different `New.BlogPost` type. The full definition of the old and new types are shown below: + +### The old schema + + public class BlogPost + { + public BlogPost() + { + this.Categories = new List(); + this.Tags = new List(); + this.Comments = new List(); + } + + public int Id { get; set; } + public int BlogId { get; set; } + public string Title { get; set; } + public string Content { get; set; } + public List Categories { get; set; } + public List Tags { get; set; } + public List Comments { get; set; } + } + + public class BlogPostComment + { + public string Content { get; set; } + public DateTime CreatedDate { get; set; } + } + +### The new schema +The 'new version' contains most changes you are likely to encounter in normal app development: + * Added, removed and renamed fields + * Non-destructive change of `int` into `long` and `double` fields + * Changed Tag collection type from a `List` to a `HashSet` + * Changed a strongly-typed `BlogPostComment` type into a loosely-typed string `Dictionary` + * Introduced a new `enum` type + * Added a nullable calculated field + + public class BlogPost + { + public BlogPost() + { + this.Labels = new List(); + this.Tags = new HashSet(); + this.Comments = new List>(); + } + + //Changed int types to both a long and a double type + public long Id { get; set; } + public double BlogId { get; set; } + + //Added new field + public BlogPostType PostType { get; set; } + + public string Title { get; set; } + public string Content { get; set; } + + //Renamed from 'Categories' to 'Labels' + public List Labels { get; set; } + + //Changed from List to a HashSet + public HashSet Tags { get; set; } + + //Changed from List of strongly-typed 'BlogPostComment' to loosely-typed string map + public List> Comments { get; set; } + + //Added pointless calculated field + public int? NoOfComments { get; set; } + } + + public enum BlogPostType + { + None, + Article, + Summary, + } + + +### 1. The do-nothing approach - using the old data with the new types +Although hard to believe, with no extra effort you can just pretend *no change was actually done* and freely access new types looking at old data. +This is possible when there is non-destructive changes (i.e. no loss of information) with new field types. +The example below uses the repository from the previous example to populate Redis with test data from the old types. Just as if nothing happened you can read the old data using the new type: + + + var repository = new BlogRepository(redisClient); + + //Populate the datastore with the old schema from the 'BlogPostBestPractice' + BlogPostBestPractice.InsertTestData(repository); + + //Create a typed-client based on the new schema + using (var redisBlogPosts = redisClient.GetTypedClient()) + { + //Automatically retrieve blog posts + IList allBlogPosts = redisBlogPosts.GetAll(); + + //Print out the data in the list of 'New.BlogPost' populated from old 'BlogPost' type + Console.WriteLine(allBlogPosts.Dump()); + /*Output: + [ + { + Id: 3, + BlogId: 2, + PostType: None, + Title: Redis, + Labels: [], + Tags: + [ + Redis, + NoSQL, + Scalability, + Performance + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-28T21:42:03.9484725Z + } + ] + }, + { + Id: 4, + BlogId: 2, + PostType: None, + Title: Couch Db, + Labels: [], + Tags: + [ + CouchDb, + NoSQL, + JSON + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-28T21:42:03.9484725Z + } + ] + }, + { + Id: 1, + BlogId: 1, + PostType: None, + Title: RavenDB, + Labels: [], + Tags: + [ + Raven, + NoSQL, + JSON, + .NET + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-28T21:42:03.9004697Z + }, + { + Content: Second Comment!, + CreatedDate: 2010-04-28T21:42:03.9004697Z + } + ] + }, + { + Id: 2, + BlogId: 1, + PostType: None, + Title: Cassandra, + Labels: [], + Tags: + [ + Cassandra, + NoSQL, + Scalability, + Hashing + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 2010-04-28T21:42:03.9004697Z + } + ] + } + ] + + */ + } + + +### 2. Using a custom translation to migrate data using application logic + +Some drawbacks with the above 'do-nothing' approach is that you will lose the data of 'renamed fields'. +There will also be times when you want the newly migrated data to have specific values that are different from the .NET built-in defaults. +When you want more control over the migration of your old data, adding a custom translation is a trivial exercise when you can do it natively in code: + + + var repository = new BlogRepository(redisClient); + + //Populate the datastore with the old schema from the 'BlogPostBestPractice' + BlogPostBestPractice.InsertTestData(repository); + + //Create a typed-client based on the new schema + using (var redisBlogPosts = redisClient.GetTypedClient()) + using (var redisNewBlogPosts = redisClient.GetTypedClient()) + { + //Automatically retrieve blog posts + IList oldBlogPosts = redisBlogPosts.GetAll(); + + //Write a custom translation layer to migrate to the new schema + var migratedBlogPosts = oldBlogPosts.ConvertAll(old => new New.BlogPost + { + Id = old.Id, + BlogId = old.BlogId, + Title = old.Title, + Content = old.Content, + Labels = old.Categories, //populate with data from renamed field + PostType = New.BlogPostType.Article, //select non-default enum value + Tags = old.Tags, + Comments = old.Comments.ConvertAll(x => new Dictionary + { { "Content", x.Content }, { "CreatedDate", x.CreatedDate.ToString() }, }), + NoOfComments = old.Comments.Count, //populate using logic from old data + }); + + //Persist the new migrated blog posts + redisNewBlogPosts.StoreAll(migratedBlogPosts); + + //Read out the newly stored blog posts + var refreshedNewBlogPosts = redisNewBlogPosts.GetAll(); + //Note: data renamed fields are successfully migrated to the new schema + Console.WriteLine(refreshedNewBlogPosts.Dump()); + /* + [ + { + Id: 3, + BlogId: 2, + PostType: Article, + Title: Redis, + Labels: + [ + NoSQL, + Cache + ], + Tags: + [ + Redis, + NoSQL, + Scalability, + Performance + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 28/04/2010 22:58:35 + } + ], + NoOfComments: 1 + }, + { + Id: 4, + BlogId: 2, + PostType: Article, + Title: Couch Db, + Labels: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + CouchDb, + NoSQL, + JSON + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 28/04/2010 22:58:35 + } + ], + NoOfComments: 1 + }, + { + Id: 1, + BlogId: 1, + PostType: Article, + Title: RavenDB, + Labels: + [ + NoSQL, + DocumentDB + ], + Tags: + [ + Raven, + NoSQL, + JSON, + .NET + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 28/04/2010 22:58:35 + }, + { + Content: Second Comment!, + CreatedDate: 28/04/2010 22:58:35 + } + ], + NoOfComments: 2 + }, + { + Id: 2, + BlogId: 1, + PostType: Article, + Title: Cassandra, + Labels: + [ + NoSQL, + Cluster + ], + Tags: + [ + Cassandra, + NoSQL, + Scalability, + Hashing + ], + Comments: + [ + { + Content: First Comment!, + CreatedDate: 28/04/2010 22:58:35 + } + ], + NoOfComments: 1 + } + ] + + */ + } + + +The end result is a datastore filled with new data populated in exactly the way you want it - ready to serve features of your new application. +In contrast, attempting the above in a typical RDBMS solution without any downtime is effectively a feat of magic that is rewardable by 999 [Stack Overflow](http://stackoverflow.com) points and a personal condolence from its grand chancellor [@JonSkeet](http://twitter.com/jonskeet) :) + +I hope this clearly illustrates differences between the two technologies. In practice you'll be amazed by the productivity gains made possible when you don't have to model your application to fit around an ORM and an RDBMS and can save objects like it was memory. + +It's always a good idea to expose yourself to new technologies so if you haven't already done so, I invite you to get started developing with Redis today to see the benefits for yourself. To get started all you need is an instance of +[the redis-server](http://code.google.com/p/servicestack/wiki/RedisWindowsDownload) (no configuration required, just unzip and run) and the dependency-free +[ServiceStack's C# Redis Client](~/redis-client/redis-client) and you're ready to go! diff --git a/src/Docs/redis-client/useful-redis-links.md b/src/Docs/redis-client/useful-redis-links.md new file mode 100644 index 00000000..e273a5a5 --- /dev/null +++ b/src/Docs/redis-client/useful-redis-links.md @@ -0,0 +1,9 @@ +Here are some links that will help you learn about and get started with Redis: + +* [Redis Home Page](http://redis.io/) +* [Redis tutorial with ServiceStack.Redis](http://www.d80.co.uk/post/2011/05/12/Redis-Tutorial-with-ServiceStackRedis.aspx) +* [NHibernate caching with Redis](http://www.d80.co.uk/post/2011/05/17/NHibernate-Caching-with-Redis.aspx) +* [Main Project website](http://code.google.com/p/redis/) +* [Mirror on GitHub](https://github.com/antirez/redis) +* [A whirlwind tour of the next big thing in NoSQL data storage (PDF)](http://no.gd/redis-presentation.pdf) +* [The Redis Book](http://redisbook.org/) diff --git a/src/Docs/text-serializers/json-csv-jsv-serializers.md b/src/Docs/text-serializers/json-csv-jsv-serializers.md new file mode 100644 index 00000000..8608c4b5 --- /dev/null +++ b/src/Docs/text-serializers/json-csv-jsv-serializers.md @@ -0,0 +1,184 @@ +[Join the new google group](http://groups.google.com/group/servicestack) or +follow [@demisbellot](http://twitter.com/demisbellot) and [@ServiceStack](http://twitter.com/servicestack) +for twitter updates. + +ServiceStack.Text is an independent, dependency-free assembly that contains all of ServiceStack's text processing functionality, including: + +Benchmarks for .NET's popular Binary and JSON Serializers are available at: [servicestack.net/benchmarks/](http://www.servicestack.net/benchmarks/) + +* [JsonSerializer](http://www.servicestack.net/mythz_blog/?p=344) +* [TypeSerializer (JSV-Format)](https://github.com/ServiceStack/ServiceStack.Text/wiki/JSV-Format) +* CsvSerializer +* [T.Dump extension method](http://www.servicestack.net/mythz_blog/?p=202) +* StringExtensions - Xml/Json/Csv/Url encoding, BaseConvert, Rot13, Hex escape, etc. +* Stream, Reflection, List, DateTime, etc extensions and utils + +## NuGet ServiceStack.Text + +![Install-Package ServiceStack.Text](http://mono.servicestack.net/img/nuget-servicestack.text.png) + +## ServiceStack.JsonSerializer - the fastest JSON Serializer for .NET +For reasons outlined [in this blog post](http://www.servicestack.net/mythz_blog/?p=344) I decided to re-use *TypeSerializer's* text processing-core to create ServiceStack.JsonSerializer - the fastest JSON Serializer for .NET. +Based on the [Northwind Benchmarks](http://www.servicestack.net/benchmarks/NorthwindDatabaseRowsSerialization.100000-times.2010-08-17.html) it's *3.6x* faster than .NET's BCL JsonDataContractSerializer and *3x* faster then the previous fastest JSON serializer benchmarked - [JSON.NET](http://json.codeplex.com/). + +## ServiceStack.CsvSerializer +As CSV is an important format in many data access and migration scenarios, it became [the latest format included in ServiceStack](~/framework/csv-format) which allows all your existing web services to take advantage of the new format without config or code-changes. As its built using the same tech that makes the JSON and JSV serializers so fast, we expect it to be the fastest POCO CSV Serializer for .NET. + +## ServiceStack.TypeSerializer and the JSV-format +Included in this project is `TypeSerializer` - The fastest and most compact text-based serializer for .NET. It's a light-weight compact Text Serializer which can be used to serialize any .NET data type including your own custom POCO's and DataContract's. More info on its JSV Format can be found on the [introductory post](http://www.servicestack.net/mythz_blog/?p=176). + +## T.Dump() Extension method +Another useful library to have in your .NET toolbox is the [T.Dump() Extension Method](http://www.servicestack.net/mythz_blog/?p=202). Under the hood it uses a *Pretty Print* Output of the JSV Format to recursively dump the contents of any .NET object. Example usage and output: + + var model = new TestModel(); + Console.WriteLine(model.Dump()); + + //Example Output + { + Int: 1, + String: One, + DateTime: 2010-04-11, + Guid: c050437f6fcd46be9b2d0806a0860b3e, + EmptyIntList: [], + IntList: + [ + 1, + 2, + 3 + ], + StringList: + [ + one, + two, + three + ], + StringIntMap: + { + a: 1, + b: 2, + c: 3 + } + } + + +# Download +### ServiceStack.Text is included with [ServiceStack.zip](https://github.com/ServiceStack/ServiceStack/downloads) +### or available to download separately in a standalone [ServiceStack.Text.zip](https://github.com/ServiceStack/ServiceStack.Text/downloads). + +
    + +#TypeSerializer Details + +Out of the box .NET provides a fairly quick but verbose Xml DataContractSerializer or a slightly more compact but slower JsonDataContractSerializer. +Both of these options are fragile and likely to break with any significant schema changes. +TypeSerializer addresses these shortcomings by being both smaller and significantly faster than the most popular options. +It's also more resilient, e.g. a strongly-typed POCO object can be deserialized back into a loosely-typed string Dictionary and vice-versa. + +With that in mind, TypeSerializer's main features are: + + - Fastest and most compact text-serializer for .NET + - Human readable and writeable, self-describing text format + - Non-invasive and configuration-free + - Resilient to schema changes + - Serializes / De-serializes any .NET data type (by convention) + + Supports custom, compact serialization of structs by overriding `ToString()` and `static T Parse(string)` methods + + Can serialize inherited, interface or 'late-bound objects' data types + + Respects opt-in DataMember custom serialization for DataContract dto types. + +These characteristics make it ideal for use anywhere you need to store or transport .NET data-types, e.g. for text blobs in a ORM, data in and out of a key-value store or as the text-protocol in .NET to .NET web services. + +As such, it's utilized within ServiceStack's other components: + - OrmLite - to store complex types on table models as text blobs in a database field and + - [ServiceStack.Redis](~/redis-client/redis-client) - to store rich POCO data types into the very fast [redis](http://code.google.com/p/redis) instances. + +# Simple API + +Like most of the interfaces in Service Stack, the API is simple and descriptive. In most cases these are the only methods that you would commonly use: + + string TypeSerializer.SerializeToString(T value); + void TypeSerializer.SerializeToWriter(T value, TextWriter writer); + + T TypeSerializer.DeserializeFromString(string value); + T TypeSerializer.DeserializeFromReader(TextReader reader); + +Where *T* can be any .NET POCO type. That's all there is - the API was intentionally left simple :) + +You may also be interested in the very useful [T.Dump() extension method](http://www.servicestack.net/mythz_blog/?p=202) for recursively viewing the contents of any C# POCO Type. + +--- + +# Performance +Type Serializer is actually the fastest and most compact *text serializer* available for .NET. +Out of all the serializers benchmarked, it is the only one to remain competitive with [protobuf-net's](http://code.google.com/p/protobuf-net/) very fast implementation of [Protocol Buffers](http://code.google.com/apis/protocolbuffers/) - google's high-speed binary protocol. + +Below is a series of benchmarks serialize the different tables in the [Northwind database](http://code.google.com/p/servicestack/source/browse/trunk/Common/Northwind.Benchmarks/Northwind.Common/DataModel/NorthwindData.cs) (3202 records) with the most popular serializers available for .NET: + +### Combined results for serializing / deserializing a single row of each table in the Northwind database 1,000,000 times +_[view the detailed benchmarks](http://www.servicestack.net/benchmarks/NorthwindDatabaseRowsSerialization.1000000-times.2010-02-06.html)_ + + + + + + + + + + + + + + + + + +
    SerializerSizePerformance
    Microsoft DataContractSerializer4.68x6.72x
    Microsoft JsonDataContractSerializer2.24x10.18x
    Microsoft BinaryFormatter5.62x9.06x
    NewtonSoft.Json2.30x8.15x
    ProtoBuf.net1x1x
    ServiceStack TypeSerializer1.78x1.92x
    + +_number of times larger in size and slower in performance than the best - lower is better_ + +Microsoft's JavaScriptSerializer was also benchmarked but excluded as it was up to 280x times slower - basically don't use it, ever. + + +# JSV Text Format (JSON + CSV) + +Type Serializer uses a hybrid CSV-style escaping + JavaScript-like text-based format that is optimized for both size and speed. I'm naming this JSV-format (i.e. JSON + CSV) + +In many ways it is similar to JavaScript, e.g. any List, Array, Collection of ints, longs, etc are stored in exactly the same way, i.e: + [1,2,3,4,5] + +Any IDictionary is serialized like JavaScript, i.e: + {A:1,B:2,C:3,D:4} + +Which also happens to be the same as C# POCO class with the values + +`new MyClass { A=1, B=2, C=3, D=4 }` + + {A:1,B:2,C:3,D:4} + +JSV is *white-space significant*, which means normal string values can be serialized without quotes, e.g: + +`new MyClass { Foo="Bar", Greet="Hello World!"}` is serialized as: + + {Foo:Bar,Greet:Hello World!} + + +### CSV escaping + +Any string with any of the following characters: `[]{},"` +is escaped using CSV-style escaping where the value is wrapped in double quotes, e.g: + +`new MyClass { Name = "Me, Junior" }` is serialized as: + + {Name:"Me, Junior"} + +A value with a double-quote is escaped with another double quote e.g: + +`new MyClass { Size = "2\" x 1\"" }` is serialized as: + + {Size:"2"" x 1"""} + + +## Rich support for resilience and schema versioning +To better illustrate the resilience of `TypeSerializer` and the JSV Format check out a real world example of it when it's used to [Painlessly migrate between old and new types in Redis](~/redis-client/schemaless-nosql-migrations). + +Support for dynamic payloads and late-bound objects is explained in the post [Versatility of JSV Late-bound objects](http://www.servicestack.net/mythz_blog/?p=314). diff --git a/src/Docs/text-serializers/json-serializer.md b/src/Docs/text-serializers/json-serializer.md new file mode 100644 index 00000000..ca8eb138 --- /dev/null +++ b/src/Docs/text-serializers/json-serializer.md @@ -0,0 +1,193 @@ +# ServiceStack JsonSerializer + +Benchmarks for .NET's JSON Serializers are available at: [docs.servicestack.net/real-world-performance](https://docs.servicestack.net/real-world-performance) + +ServiceStack's JsonSerializer is optimized for serializing C# POCO types in and out of JSON as fast, compact and cleanly as possible. In most cases C# objects serializes as you would expect them to without added json extensions or serializer-specific artefacts. + +JsonSerializer provides a simple API that allows you to serialize any .NET generic or runtime type into a string, TextWriter/TextReader or Stream. + +### Serialization API + + string SerializeToString(T) + void SerializeToWriter(T, TextWriter) + void SerializeToStream(T, Stream) + string SerializeToString(object, Type) + void SerializeToWriter(object, Type, TextWriter) + void SerializeToStream(object, Type, Stream) + +### Deserialization API + + T DeserializeFromString(string) + T DeserializeFromReader(TextReader) + object DeserializeFromString(string, Type) + object DeserializeFromReader(reader, Type) + object DeserializeFromStream(Type, Stream) + T DeserializeFromStream(Stream) + +### Extension methods + + string ToJson(this T) + T FromJson(this string) + +Convenient **ToJson/FromJson** extension methods are also included reducing the amount of code required, e.g: + + new []{ 1, 2, 3 }.ToJson() //= [1,2,3] + "[1,2,3]".FromJson() //= int []{ 1, 2, 3 } + +## JSON Format + +JSON is a lightweight text serialization format with a spec that's so simple that it fits on one page: [http://www.json.org](json.org). + +The only valid values in JSON are: + + * string + * number + * object + * array + * true + * false + * null + +Where most allowed values are scalar and the only complex types available are objects and arrays. Although limited, the above set of types make a good fit and can express most programming data structures. + +### number, true, false types + +All C# boolean and numeric data types are stored as-is without quotes. + +### null type + +For the most compact output null values are omitted from the serialized by default. If you want to include null values set the global configuration: + + JsConfig.IncludeNullValues = true; + +### string type + +All other scalar values are stored as strings that are surrounded with double quotes. + +### C# Structs and Value Types + +Because a C# struct is a value type whose public properties are normally just convenience properties around a single scalar value, they are ignored instead the **TStruct.ToString()** method is used to serialize and either the **static TStruct.Parse()** method or **new TStruct(string)** constructor will be used to deserialize the value type if it exists. + +### array type + +Any List, Queue, Stack, Array, Collection, Enumerables including custom enumerable types are stored in exactly the same way as a JavaScript array literal, i.e: + + [1,2,3,4,5] + +All elements in an array must be of the same type. If a custom type is both an IEnumerable and has properties it will be treated as an array and the extra properties will be ignored. + +### object type + +The JSON object type is the most flexible and is how most complex .NET types are serialized. The JSON object type is a key-value pair JavaScript object literal where the key is always a double-quoted string. + +Any IDictionary is serialized into a standard JSON object, i.e: + + {"A":1,"B":2,"C":3,"D":4} + +Which happens to be the same as C# POCO types (inc. Interfaces) with the values: + +`new MyClass { A=1, B=2, C=3, D=4 }` + + {"A":1,"B":2,"C":3,"D":4} + +Only public properties on reference types are serialized with the C# Property Name used for object key and the Property Value as the value. At the moment it is not possible to customize the Property Name. + +JsonSerializer also supports serialization of anonymous types in much the same way: + +`new { A=1, B=2, C=3, D=4 }` + + {"A":1,"B":2,"C":3,"D":4} + + +## Custom Serialization + +Although JsonSerializer is optimized for serializing .NET POCO types, it still provides some options to change the convention-based serialization routine. + +### Using Structs to Customize JSON + +This makes it possible to customize the serialization routine and provide an even more compact wire format. + +E.g. Instead of using a JSON object to represent a point + + { Width=20, Height=10 } + +You could use a struct and reduce it to just: + + "20x10" + +By overriding **ToString()** and providing a static **Size Parse()** method: + + public struct Size + { + public double Width { get; set; } + public double Height { get; set; } + + public override string ToString() + { + return Width + "x" + Height; + } + + public static Size Parse(string json) + { + var size = json.Split('x'); + return new Size { + Width = double.Parse(size[0]), + Height = double.Parse(size[1]) + }; + } + } + +Which would change it to the more compact JSON output: + + new Size { Width = 20, Height = 10 }.ToJson() // = "20x10" + +That allows you to deserialize it back in the same way: + + var size = "20x10".FromJson(); + +### Using Custom IEnumerable class to serialize a JSON array + +In addition to using a Struct you can optionally use a custom C# IEnumerable type to provide a strong-typed wrapper around a JSON array: + + public class Point : IEnumerable + { + double[] points = new double[2]; + + public double X + { + get { return points[0]; } + set { points[0] = value; } + } + + public double Y + { + get { return points[1]; } + set { points[1] = value; } + } + + public IEnumerator GetEnumerator() + { + foreach (var point in points) + yield return point; + } + } + +Which serializes the Point into a compact JSON array: + + new Point { X = 1, Y = 2 }.ToJson() // = [1,2] + +## Custom Deserialization + +Because the same wire format shared between Dictionaries, POCOs and anonymous types, in most cases what you serialize with one type can be deserialized with another, i.e. an Anonymous type can be deserialized back into a Dictionary which can be deserialized into a strong-typed POCO and vice-versa. + +Although the JSON Serializer is best optimized for serializing and deserializing .NET types, it's flexible enough to consume 3rd party JSON apis although this generally requires custom de-serialization to convert it into an idiomatic .NET type. + +[GitHubRestTests.cs](https://github.com/ServiceStack/ServiceStack.Text/blob/master/tests/ServiceStack.Text.Tests/UseCases/GitHubRestTests.cs) + + 1. Using [JsonObject](https://github.com/ServiceStack/ServiceStack.Text/blob/master/src/ServiceStack.Text/JsonObject.cs) + 2. Using Generic .NET Collection classes + 3. Using Customized DTO's in the shape of the 3rd party JSON response + +[CentroidTests](https://github.com/ServiceStack/ServiceStack.Text/blob/master/tests/ServiceStack.Text.Tests/UseCases/CentroidTests.cs) is another example that uses the JsonObject to parse a complex custom JSON response. + + diff --git a/src/Docs/text-serializers/jsv-format.md b/src/Docs/text-serializers/jsv-format.md new file mode 100644 index 00000000..5bf71561 --- /dev/null +++ b/src/Docs/text-serializers/jsv-format.md @@ -0,0 +1,37 @@ +# JSV Text Format (JSON + CSV) + +Type Serializer uses a hybrid CSV-style escaping + JavaScript-like text-based format that is optimized for both size and speed. I'm naming this JSV-format (i.e. JSON + CSV) + +In many ways it is similar to JavaScript, e.g. any List, Array, Collection of ints, longs, etc are stored in exactly the same way, i.e: + [1,2,3,4,5] + +Any IDictionary is serialized like JavaScript, i.e: + {A:1,B:2,C:3,D:4} + +Which also happens to be the same as C# POCO class with the values + +`new MyClass { A=1, B=2, C=3, D=4 }` + + {A:1,B:2,C:3,D:4} + +JSV is *white-space significant*, which means normal string values can be serialized without quotes, e.g: + +`new MyClass { Foo="Bar", Greet="Hello World!"}` is serialized as: + + {Foo:Bar,Greet:Hello World!} + + +### CSV escaping + +Any string with any of the following characters: `[]{},"` +is escaped using CSV-style escaping where the value is wrapped in double quotes, e.g: + +`new MyClass { Name = "Me, Junior" }` is serialized as: + + {Name:"Me, Junior"} + +A value with a double-quote is escaped with another double quote e.g: + +`new MyClass { Size = "2\" x 1\"" }` is serialized as: + + {Size:"2"" x 1"""} diff --git a/src/Docs/text-serializers/override-mvc-jsonresult.md b/src/Docs/text-serializers/override-mvc-jsonresult.md new file mode 100644 index 00000000..939a16c1 --- /dev/null +++ b/src/Docs/text-serializers/override-mvc-jsonresult.md @@ -0,0 +1,51 @@ +# Use ServiceStack's JsonSerializer in ASP.NET MVC + +The easiest way to get an instant perf boost when developing JSON services with MVC is to +override MVC's JsonResult to use ServiceStack's JsonSerializer instead of the default slow +JSON serializer shipped with ASP.NET MVC. + +Our benchmarks show ServiceStack's JsonSerializer +**[is over 3x faster than JSON.NET](http://www.servicestack.net/benchmarks/NorthwindDatabaseRowsSerialization.100000-times.2010-08-17.html)** +using Microsoft's sample real-world Northwind database whilst others are reporting similar success: + + - [JSON.NET vs ServiceStack](http://daniel.wertheim.se/2011/02/07/json-net-vs-servicestack/) + - [C# and spray painting vegetables on ServiceStack.NET](http://fir3pho3nixx.blogspot.com/2011/04/servicestacknet.html) + + +You can change the default ASP.NET MVCs JsonResult to use ServiceStack's JsonSerializer +by creating your own base controller that overrides `Json(object,string,Encoding)` with the +following implementation: + + public abstract class ApplicationController : Controller + { + protected ActionResult RespondTo(Action format) { + return new FormatResult(format); + } + + protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior) { + return new ServiceStackJsonResult { + Data = data, + ContentType = contentType, + ContentEncoding = contentEncoding + }; + } + } + + public class ServiceStackJsonResult : JsonResult + { + public override void ExecuteResult(ControllerContext context) { + HttpResponseBase response = context.HttpContext.Response; + response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json"; + + if (ContentEncoding != null) { + response.ContentEncoding = ContentEncoding; + } + + if (Data != null) { + response.Write(JsonSerializer.SerializeToString(Data)); + } + } + } + +Special thanks to [@JakeScott](http://twitter.com/JakeScott) for his +[gist for the above source code](https://gist.github.com/1037528). \ No newline at end of file diff --git a/src/MonoTouch/RestFilesClient/Lib/RestFiles.ServiceModel.dll b/src/MonoTouch/RestFilesClient/Lib/RestFiles.ServiceModel.dll new file mode 100755 index 00000000..7b8996e0 Binary files /dev/null and b/src/MonoTouch/RestFilesClient/Lib/RestFiles.ServiceModel.dll differ diff --git a/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Common.MonoTouch.dll b/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Common.MonoTouch.dll new file mode 100755 index 00000000..f891d7a7 Binary files /dev/null and b/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Common.MonoTouch.dll differ diff --git a/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Interfaces.MonoTouch.dll b/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Interfaces.MonoTouch.dll new file mode 100755 index 00000000..e4c146fd Binary files /dev/null and b/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Interfaces.MonoTouch.dll differ diff --git a/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Text.MonoTouch.dll b/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Text.MonoTouch.dll new file mode 100755 index 00000000..081a23ff Binary files /dev/null and b/src/MonoTouch/RestFilesClient/Lib/ServiceStack.Text.MonoTouch.dll differ diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient.sln b/src/MonoTouch/RestFilesClient/RestFilesClient.sln new file mode 100644 index 00000000..d4e7b09d --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestFilesClient", "RestFilesClient\RestFilesClient.csproj", "{B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|iPhoneSimulator = Release|iPhoneSimulator + Debug|iPhone = Debug|iPhone + Release|iPhone = Release|iPhone + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Debug|iPhone.ActiveCfg = Debug|iPhone + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Debug|iPhone.Build.0 = Debug|iPhone + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Release|iPhone.ActiveCfg = Release|iPhone + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Release|iPhone.Build.0 = Release|iPhone + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = RestFilesClient\RestFilesClient.csproj + EndGlobalSection +EndGlobal diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/Info.plist b/src/MonoTouch/RestFilesClient/RestFilesClient/Info.plist new file mode 100644 index 00000000..4a1bad96 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/Info.plist @@ -0,0 +1,17 @@ + + + + + MinimumOSVersion + 3.0 + NSMainNibFile + MainWindow + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/Main.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/Main.cs new file mode 100644 index 00000000..74fe7dbc --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/Main.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using MonoTouch.Foundation; +using MonoTouch.UIKit; + +using ServiceStack.ServiceClient.Web; +using ServiceStack.Text; +using ServiceStack.Text.Common; +using ServiceStack.Service; +using RestFiles.ServiceModel.Operations; +using RestFiles.ServiceModel.Types; + +namespace RestFilesClient +{ + public class Application + { + static void Main (string[] args) + { + UIApplication.Main (args); + } + } + + // The name AppDelegate is referenced in the MainWindow.xib file. + public partial class AppDelegate : UIApplicationDelegate + { + JsonServiceClient gateway = new JsonServiceClient("http://servicestack.net/RestFiles"); + //JsvServiceClient gateway = new JsvServiceClient("http://servicestack.net/RestFiles"); + + // This method is invoked when the application has loaded its UI and its ready to run + public override bool FinishedLaunching (UIApplication app, NSDictionary options) + { + // If you have defined a view, add it here: + // window.AddSubview (navigationController.View); + + window.MakeKeyAndVisible(); + + return true; + } + + // This method is required in iPhoneOS 3.0 + public override void OnActivated (UIApplication application) + { + } + + partial void getFilesAtPath (MonoTouch.UIKit.UIButton sender) + { + //calling sync web service + var response = gateway.Get(txtPath.Text); + txtResults.Text = response.Dump(); + + var alertView = new UIAlertView("Alert", "getFiles Sync: " + txtPath.Text, null, "Cancel"); + alertView.Show(); + } + + partial void getFilesAtPathAsync (MonoTouch.UIKit.UIButton sender) + { + //calling async web service + gateway.GetAsync(txtPath.Text, + r => InvokeOnMainThread(() => txtResults.Text = r.Dump()), + null); + } + + } +} + diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/MainWindow.xib b/src/MonoTouch/RestFilesClient/RestFilesClient/MainWindow.xib new file mode 100644 index 00000000..0bccb2bc --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/MainWindow.xib @@ -0,0 +1,468 @@ + + + + 768 + 10J869 + 823 + 1038.35 + 461.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 132 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + + 1316 + + YES + + + 1316 + {{8, 34}, {42, 21}} + + NO + YES + 7 + NO + IBCocoaTouchFramework + Path: + + 1 + MCAwIDAAA + + + 3 + MQA + + 1 + 10 + + + + 1316 + {{55, 29}, {128, 31}} + + NO + YES + IBCocoaTouchFramework + 0 + /files + 3 + + 3 + MAA + + 2 + + + YES + 17 + + IBCocoaTouchFramework + + + + + 1316 + {{188, 25}, {59, 37}} + + NO + IBCocoaTouchFramework + 0 + 0 + + Helvetica-Bold + 15 + 16 + + 1 + sync + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MC41AA + + + + + 1316 + {{250, 25}, {67, 37}} + + NO + IBCocoaTouchFramework + 0 + 0 + + 1 + async + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + 1316 + {{0, 68}, {320, 412}} + + + 1 + MC45MTg0NzgyNjA5IDAuOTE4NDc4MjYwOSAwLjkxODQ3ODI2MDkAA + + YES + YES + IBCocoaTouchFramework + + + 2 + IBCocoaTouchFramework + + + + + {320, 480} + + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + + + + + YES + + + delegate + + + + 5 + + + + window + + + + 7 + + + + getFilesAtPath: + + + 7 + + 12 + + + + txtResults + + + + 13 + + + + txtPath + + + + 14 + + + + getFilesAtPathAsync: + + + 7 + + 17 + + + + + YES + + 0 + + + + + + 2 + + + YES + + + + + + + + + + -1 + + + File's Owner + + + 4 + + + App Delegate + + + -2 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 11 + + + + + 15 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.IBPluginDependency + 10.IBViewBoundsToFrameTransform + 11.IBPluginDependency + 11.IBViewBoundsToFrameTransform + 15.IBPluginDependency + 15.IBViewBoundsToFrameTransform + 2.IBAttributePlaceholdersKey + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 2.UIWindow.visibleAtLaunch + 4.CustomClassName + 4.IBPluginDependency + 8.IBPluginDependency + 8.IBViewBoundsToFrameTransform + 9.IBPluginDependency + 9.IBViewBoundsToFrameTransform + + + YES + UIApplication + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDSQAAwnAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAAAAAAAAw+iAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABDfwAAwnAAAA + + + YES + + + YES + + + {{600, 261}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + AppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABBAAAAwiAAAA + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + P4AAAL+AAABCXAAAwmgAAA + + + + + YES + + + YES + + + + + YES + + + YES + + + + 17 + + + + YES + + AppDelegate + + YES + + YES + getFilesAtPath: + getFilesAtPathAsync: + + + YES + id + id + + + + YES + + YES + getFilesAtPath: + getFilesAtPathAsync: + + + YES + + getFilesAtPath: + id + + + getFilesAtPathAsync: + id + + + + + YES + + YES + txtPath + txtResults + window + + + YES + UITextField + UITextView + id + + + + YES + + YES + txtPath + txtResults + window + + + YES + + txtPath + UITextField + + + txtResults + UITextView + + + window + id + + + + + IBUserSource + + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + + 3 + 132 + + diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/MainWindow.xib.designer.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/MainWindow.xib.designer.cs new file mode 100644 index 00000000..9b600cf7 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/MainWindow.xib.designer.cs @@ -0,0 +1,67 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +namespace RestFilesClient { + + + // Base type probably should be MonoTouch.Foundation.NSObject or subclass + [MonoTouch.Foundation.Register("AppDelegate")] + public partial class AppDelegate { + + private MonoTouch.UIKit.UIWindow __mt_window; + + private MonoTouch.UIKit.UITextView __mt_txtResults; + + private MonoTouch.UIKit.UITextField __mt_txtPath; + + #pragma warning disable 0169 + [MonoTouch.Foundation.Export("getFilesAtPath:")] + partial void getFilesAtPath (MonoTouch.UIKit.UIButton sender); + + [MonoTouch.Foundation.Export("getFilesAtPathAsync:")] + partial void getFilesAtPathAsync (MonoTouch.UIKit.UIButton sender); + + [MonoTouch.Foundation.Connect("window")] + private MonoTouch.UIKit.UIWindow window { + get { + this.__mt_window = ((MonoTouch.UIKit.UIWindow)(this.GetNativeField("window"))); + return this.__mt_window; + } + set { + this.__mt_window = value; + this.SetNativeField("window", value); + } + } + + [MonoTouch.Foundation.Connect("txtResults")] + private MonoTouch.UIKit.UITextView txtResults { + get { + this.__mt_txtResults = ((MonoTouch.UIKit.UITextView)(this.GetNativeField("txtResults"))); + return this.__mt_txtResults; + } + set { + this.__mt_txtResults = value; + this.SetNativeField("txtResults", value); + } + } + + [MonoTouch.Foundation.Connect("txtPath")] + private MonoTouch.UIKit.UITextField txtPath { + get { + this.__mt_txtPath = ((MonoTouch.UIKit.UITextField)(this.GetNativeField("txtPath"))); + return this.__mt_txtPath; + } + set { + this.__mt_txtPath = value; + this.SetNativeField("txtPath", value); + } + } + } +} diff --git a/src/RestFiles/RestFiles.ServiceModel/Operations/Files.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Operations/Files.cs similarity index 100% rename from src/RestFiles/RestFiles.ServiceModel/Operations/Files.cs rename to src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Operations/Files.cs diff --git a/src/RestFiles/RestFiles.ServiceModel/Operations/RevertFiles.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Operations/RevertFiles.cs similarity index 100% rename from src/RestFiles/RestFiles.ServiceModel/Operations/RevertFiles.cs rename to src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Operations/RevertFiles.cs diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/File.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/File.cs new file mode 100644 index 00000000..15410e37 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/File.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.Serialization; + +namespace RestFiles.ServiceModel.Types +{ + [DataContract] + public class File + { + [DataMember] + public string Name { get; set; } + + [DataMember] + public string Extension { get; set; } + + [DataMember] + public long FileSizeBytes { get; set; } + + [DataMember] + public DateTime ModifiedDate { get; set; } + + [DataMember] + public bool IsTextFile { get; set; } + } +} \ No newline at end of file diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/FileResult.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/FileResult.cs new file mode 100644 index 00000000..ce2460f3 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/FileResult.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Serialization; + +namespace RestFiles.ServiceModel.Types +{ + [DataContract] + public class FileResult + { + [DataMember] + public string Name { get; set; } + + [DataMember] + public string Extension { get; set; } + + [DataMember] + public long FileSizeBytes { get; set; } + + [DataMember] + public DateTime ModifiedDate { get; set; } + + [DataMember] + public bool IsTextFile { get; set; } + + [DataMember] + public string Contents { get; set; } + } +} \ No newline at end of file diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/Folder.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/Folder.cs new file mode 100644 index 00000000..dd25dcc2 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/Folder.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.Serialization; + +namespace RestFiles.ServiceModel.Types +{ + [DataContract] + public class Folder + { + [DataMember] + public string Name { get; set; } + + [DataMember] + public DateTime ModifiedDate { get; set; } + + [DataMember] + public int FileCount { get; set; } + } +} \ No newline at end of file diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/FolderResult.cs b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/FolderResult.cs new file mode 100644 index 00000000..7bef9a38 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFiles.ServiceModel/Types/FolderResult.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace RestFiles.ServiceModel.Types +{ + [DataContract] + public class FolderResult + { + public FolderResult() + { + Folders = new List(); + Files = new List(); + } + + [DataMember] + public List Folders { get; set; } + + [DataMember] + public List Files { get; set; } + } +} \ No newline at end of file diff --git a/src/MonoTouch/RestFilesClient/RestFilesClient/RestFilesClient.csproj b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFilesClient.csproj new file mode 100644 index 00000000..6bfb64d1 --- /dev/null +++ b/src/MonoTouch/RestFilesClient/RestFilesClient/RestFilesClient.csproj @@ -0,0 +1,93 @@ + + + + Debug + iPhoneSimulator + 9.0.21022 + 2.0 + {B8A976FA-7EFE-4096-ABA9-61AFC9CCD525} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + RestFilesClient + RestFilesClient + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG + prompt + 4 + None + true + false + + + none + false + bin\iPhoneSimulator\Release + prompt + 4 + None + false + + + true + full + false + bin\iPhone\Debug + DEBUG + prompt + 4 + true + iPhone Developer + false + + + none + false + bin\iPhone\Release + prompt + 4 + false + iPhone Developer + + + + + + + ..\Lib\ServiceStack.Common.MonoTouch.dll + + + ..\Lib\ServiceStack.Interfaces.MonoTouch.dll + + + ..\Lib\ServiceStack.Text.MonoTouch.dll + + + + + + + + + MainWindow.xib + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/MonoTouch/RestFilesClient/copy.sh b/src/MonoTouch/RestFilesClient/copy.sh new file mode 100755 index 00000000..d21568ba --- /dev/null +++ b/src/MonoTouch/RestFilesClient/copy.sh @@ -0,0 +1,2 @@ +cp /Users/mythz/src/ServiceStack.Text/src/ServiceStack.Text/bin/MonoTouch/*.dll Lib/ +cp /Users/mythz/src/ServiceStack.Examples/src/RestFiles/RestFiles.ServiceModel/bin/Release/RestFiles.ServiceModel.dll Lib/ \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/AnswersService.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/AnswersService.cs index 625266e3..7599c995 100644 --- a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/AnswersService.cs +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/AnswersService.cs @@ -1,55 +1,32 @@ -using System; -using System.Runtime.Serialization; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface; -using ServiceStack.ServiceInterface.ServiceModel; +using RedisStackOverflow.ServiceModel; +using ServiceStack; namespace RedisStackOverflow.ServiceInterface { - [DataContract] - [RestService("/answers")] - public class Answers - { - [DataMember] - public int UserId { get; set; } - [DataMember] - public int AnswerId { get; set; } - - [DataMember] - public int QuestionId { get; set; } - - [DataMember] - public string Content { get; set; } - } - - [DataContract] - public class AnswersResponse : IHasResponseStatus - { - //For automatic injection of service exceptions - [DataMember] public ResponseStatus ResponseStatus { get; set; } - } - - public class AnswersService - : RestServiceBase - { - public IRepository Repository { get; set; } - - public override object OnPost(Answers request) - { - Repository.StoreAnswer(new Answer - { - UserId = request.UserId, - QuestionId = request.QuestionId, - Content = request.Content - }); - return new AnswersResponse(); - } - - public override object OnDelete(Answers request) - { - Repository.DeleteAnswer(request.QuestionId, request.AnswerId); - return new AnswersResponse(); - } - } + /// + /// Create your ServiceStack rest-ful web service implementation. + /// + public class AnswersService : Service + { + /// + /// Gets or sets the repository. The built-in IoC used with ServiceStack autowires this property. + /// + public IRepository Repository { get; set; } + + public void Post(Answers request) + { + Repository.StoreAnswer(new Answer + { + UserId = request.UserId, + QuestionId = request.QuestionId, + Content = request.Content + }); + } + + public void Delete(Answers request) + { + Repository.DeleteAnswer(request.QuestionId, request.AnswerId); + } + } } \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/IRepository.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/IRepository.cs index 33ff995b..e0b59519 100644 --- a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/IRepository.cs +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/IRepository.cs @@ -1,416 +1,419 @@ using System; using System.Collections.Generic; using System.Linq; -using ServiceStack.Common.Utils; +using RedisStackOverflow.ServiceModel; +using ServiceStack; using ServiceStack.Redis; -using ServiceStack.Common.Extensions; namespace RedisStackOverflow.ServiceInterface { - public interface IRepository - { - User GetOrCreateUser(User user); + public interface IRepository + { + User GetOrCreateUser(User user); - UserStat GetUserStats(long userId); + UserStat GetUserStats(long userId); - List GetAllQuestions(); + List GetAllQuestions(); - List GetRecentQuestionResults(int skip, int take); + List GetRecentQuestionResults(int skip, int take); - List GetQuestionsByUser(long userId); + List GetQuestionsByUser(long userId); - List GetQuestionsTaggedWith(string tagName); + List GetQuestionsTaggedWith(string tagName); - void StoreQuestion(Question question); + void StoreQuestion(Question question); - void StoreAnswer(Answer answer); + void StoreAnswer(Answer answer); - List GetAnswersForQuestion(long questionId); + List GetAnswersForQuestion(long questionId); - void VoteQuestionUp(long userId, long questionId); + void VoteQuestionUp(long userId, long questionId); - void VoteQuestionDown(long userId, long questionId); + void VoteQuestionDown(long userId, long questionId); - void VoteAnswerUp(long userId, long answerId); + void VoteAnswerUp(long userId, long answerId); - void VoteAnswerDown(long userId, long answerId); + void VoteAnswerDown(long userId, long answerId); - QuestionStat GetQuestionStats(long questionId); + QuestionStat GetQuestionStats(long questionId); - QuestionResult GetQuestion(long questionId); + QuestionResult GetQuestion(long questionId); - List GetUsersByIds(IEnumerable userIds); + List GetUsersByIds(IEnumerable userIds); - SiteStats GetSiteStats(); - - void DeleteQuestion(long questionId); + SiteStats GetSiteStats(); + + void DeleteQuestion(long questionId); - void DeleteAnswer(long questionId, long answerId); - } + void DeleteAnswer(long questionId, long answerId); + } - public class Repository : IRepository - { - //Definition of all the redis keys that are used for indexes - static class TagIndex - { - public static string Questions(string tag) { return "urn:tags>q:" + tag.ToLower(); } - public static string All { get { return "urn:tags"; } } - } - - static class QuestionUserIndex - { - public static string UpVotes(long questionId) { return "urn:q>user+:" + questionId; } - public static string DownVotes(long questionId) { return "urn:q>user-:" + questionId; } - } - - static class UserQuestionIndex - { - public static string Questions(long userId) { return "urn:user>q:" + userId; } - public static string UpVotes(long userId) { return "urn:user>q+:" + userId; } - public static string DownVotes(long userId) { return "urn:user>q-:" + userId; } - } - - static class AnswerUserIndex - { - public static string UpVotes(long answerId) { return "urn:a>user+:" + answerId; } - public static string DownVotes(long answerId) { return "urn:a>user-:" + answerId; } - } - - static class UserAnswerIndex - { - public static string Answers(long userId) { return "urn:user>a:" + userId; } - public static string UpVotes(long userId) { return "urn:user>a+:" + userId; } - public static string DownVotes(long userId) { return "urn:user>a-:" + userId; } - } - - IRedisClientsManager RedisManager { get; set; } - - public Repository(IRedisClientsManager redisManager) - { - RedisManager = redisManager; - } - - public User GetOrCreateUser(User user) - { - if (user.DisplayName.IsNullOrEmpty()) - throw new ArgumentNullException("DisplayName"); - - var userIdAliasKey = "id:User:DisplayName:" + user.DisplayName.ToLower(); - - using (var redis = RedisManager.GetClient()) - { - //Get a typed version of redis client that works with - var redisUsers = redis.As(); - - //Find user by DisplayName if exists - var userKey = redis.GetValue(userIdAliasKey); - if (userKey != null) - return redisUsers.GetValue(userKey); - - //Generate Id for New User - if (user.Id == default(long)) - user.Id = redisUsers.GetNextSequence(); - - redisUsers.Store(user); - - //Save reference to User key using the DisplayName alias - redis.SetEntry(userIdAliasKey, user.CreateUrn()); - - return redisUsers.GetById(user.Id); - } - } - - public UserStat GetUserStats(long userId) - { - using (var redis = RedisManager.GetClient()) - { - return new UserStat - { - UserId = userId, - QuestionsCount = redis.GetSetCount(UserQuestionIndex.Questions(userId)), - AnswersCount = redis.GetSetCount(UserAnswerIndex.Answers(userId)), - }; - } - } - - public List GetAllQuestions() - { - return RedisManager.ExecAs(redisQuestions => redisQuestions.GetAll()).ToList(); - } - - public List GetRecentQuestionResults(int skip, int take) - { - using (var redis = RedisManager.GetReadOnlyClient()) - { - return ToQuestionResults(redis.As().GetLatestFromRecentsList(skip, take)); - } - } - - public List GetQuestionsByUser(long userId) - { - using (var redis = RedisManager.GetReadOnlyClient()) - { - var questionIds = redis.GetAllItemsFromSet(UserQuestionIndex.Questions(userId)); - var questions = redis.As().GetByIds(questionIds); - return ToQuestionResults(questions); - } - } - - public List GetQuestionsTaggedWith(string tagName) - { - using (var redis = RedisManager.GetReadOnlyClient()) - { - var questionIds = redis.GetAllItemsFromSet(TagIndex.Questions(tagName)); - var questions = redis.As().GetByIds(questionIds); - return ToQuestionResults(questions); - } - } - - private List ToQuestionResults(IEnumerable questions) - { - var uniqueUserIds = questions.ConvertAll(x => x.UserId).ToHashSet(); - var usersMap = GetUsersByIds(uniqueUserIds).ToDictionary(x => x.Id); - - var results = questions.ConvertAll(x => new QuestionResult { Question = x }); - var resultsMap = results.ToDictionary(q => q.Question.Id); - - results.ForEach(x => x.User = usersMap[x.Question.UserId]); - - //Batch multiple operations in a single pipelined transaction (i.e. for a single network request/response) - RedisManager.ExecTrans(trans => - { - foreach (var question in questions) - { - var q = question; - - trans.QueueCommand(r => r.GetSetCount(QuestionUserIndex.UpVotes(q.Id)), - voteUpCount => resultsMap[q.Id].VotesUpCount = voteUpCount); - - trans.QueueCommand(r => r.GetSetCount(QuestionUserIndex.DownVotes(q.Id)), - voteDownCount => resultsMap[q.Id].VotesDownCount = voteDownCount); - - trans.QueueCommand(r => r.As().GetRelatedEntitiesCount(q.Id), - answersCount => resultsMap[q.Id].AnswersCount = answersCount); - } - }); - - return results; - } - - /// - /// Delete question by performing compensating actions to StoreQuestion() to keep the datastore in a consistent state - /// - /// - public void DeleteQuestion(long questionId) - { - using (var redis = RedisManager.GetClient()) - { - var redisQuestions = redis.As(); - - var question = redisQuestions.GetById(questionId); - if (question == null) return; - - //decrement score in tags list - question.Tags.ForEach(tag => redis.IncrementItemInSortedSet(TagIndex.All, tag, -1)); - - //remove all related answers - redisQuestions.DeleteRelatedEntities(questionId); - - //remove this question from user index - redis.RemoveItemFromSet(UserQuestionIndex.Questions(question.UserId), questionId.ToString()); - - //remove tag => questions index for each tag - question.Tags.ForEach(tag => redis.RemoveItemFromSet(TagIndex.Questions(tag), questionId.ToString())); - - redisQuestions.DeleteById(questionId); - } - } - - public void StoreQuestion(Question question) - { - using (var redis = RedisManager.GetClient()) - { - var redisQuestions = redis.As(); - - if (question.Tags == null) question.Tags = new List(); - if (question.Id == default(long)) - { - question.Id = redisQuestions.GetNextSequence(); - question.CreatedDate = DateTime.UtcNow; - - //Increment the popularity for each new question tag - question.Tags.ForEach(tag => redis.IncrementItemInSortedSet(TagIndex.All, tag, 1)); - } - - redisQuestions.Store(question); - redisQuestions.AddToRecentsList(question); - redis.AddItemToSet(UserQuestionIndex.Questions(question.UserId), question.Id.ToString()); - - //Populate tag => questions index for each tag - question.Tags.ForEach(tag => redis.AddItemToSet(TagIndex.Questions(tag), question.Id.ToString())); - } - } - - /// - /// Delete Answer by performing compensating actions to StoreAnswer() to keep the datastore in a consistent state - /// - /// - /// - public void DeleteAnswer(long questionId, long answerId) - { - using (var redis = RedisManager.GetClient()) - { - var answer = redis.As().GetRelatedEntities(questionId).FirstOrDefault(x => x.Id == answerId); - if (answer == null) return; - - redis.As().DeleteRelatedEntity(questionId, answerId); - - //remove user => answer index - redis.RemoveItemFromSet(UserAnswerIndex.Answers(answer.UserId), answerId.ToString()); - } - } - - public void StoreAnswer(Answer answer) - { - using (var redis = RedisManager.GetClient()) - { - if (answer.Id == default(long)) - { - answer.Id = redis.As().GetNextSequence(); - answer.CreatedDate = DateTime.UtcNow; - } - - //Store as a 'Related Answer' to the parent Question - redis.As().StoreRelatedEntities(answer.QuestionId, answer); - //Populate user => answer index - redis.AddItemToSet(UserAnswerIndex.Answers(answer.UserId), answer.Id.ToString()); - } - } - - public List GetAnswersForQuestion(long questionId) - { - using (var redis = RedisManager.GetClient()) - { - return redis.As().GetRelatedEntities(questionId); - } - } - - public void VoteQuestionUp(long userId, long questionId) - { - //Populate Question => User and User => Question set indexes in a single transaction - RedisManager.ExecTrans(trans => - { - //Register upvote against question and remove any downvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(QuestionUserIndex.UpVotes(questionId), userId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(QuestionUserIndex.DownVotes(questionId), userId.ToString())); - - //Register upvote against user and remove any downvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(UserQuestionIndex.UpVotes(userId), questionId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(UserQuestionIndex.DownVotes(userId), questionId.ToString())); - }); - } - - public void VoteQuestionDown(long userId, long questionId) - { - //Populate Question => User and User => Question set indexes in a single transaction - RedisManager.ExecTrans(trans => - { - //Register downvote against question and remove any upvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(QuestionUserIndex.DownVotes(questionId), userId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(QuestionUserIndex.UpVotes(questionId), userId.ToString())); - - //Register downvote against user and remove any upvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(UserQuestionIndex.DownVotes(userId), questionId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(UserQuestionIndex.UpVotes(userId), questionId.ToString())); - }); - } - - public void VoteAnswerUp(long userId, long answerId) - { - //Populate Question => User and User => Question set indexes in a single transaction - RedisManager.ExecTrans(trans => - { - //Register upvote against answer and remove any downvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(AnswerUserIndex.UpVotes(answerId), userId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(AnswerUserIndex.DownVotes(answerId), userId.ToString())); - - //Register upvote against user and remove any downvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(UserAnswerIndex.UpVotes(userId), answerId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(UserAnswerIndex.DownVotes(userId), answerId.ToString())); - }); - } - - public void VoteAnswerDown(long userId, long answerId) - { - //Populate Question => User and User => Question set indexes in a single transaction - RedisManager.ExecTrans(trans => - { - //Register downvote against answer and remove any upvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(AnswerUserIndex.DownVotes(answerId), userId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(AnswerUserIndex.UpVotes(answerId), userId.ToString())); - - //Register downvote against user and remove any upvotes if any - trans.QueueCommand(redis => redis.AddItemToSet(UserAnswerIndex.DownVotes(userId), answerId.ToString())); - trans.QueueCommand(redis => redis.RemoveItemFromSet(UserAnswerIndex.UpVotes(userId), answerId.ToString())); - }); - } - - public QuestionResult GetQuestion(long questionId) - { - var question = RedisManager.ExecAs(redisQuestions => redisQuestions.GetById(questionId)); - if (question == null) return null; - - var result = ToQuestionResults(new[] { question })[0]; - var answers = GetAnswersForQuestion(questionId); - var uniqueUserIds = answers.ConvertAll(x => x.UserId).ToHashSet(); - var usersMap = GetUsersByIds(uniqueUserIds).ToDictionary(x => x.Id); - - result.Answers = answers.ConvertAll(answer => - new AnswerResult { Answer = answer, User = usersMap[answer.UserId] }); - - return result; - } - - public List GetUsersByIds(IEnumerable userIds) - { - return RedisManager.ExecAs(redisUsers => redisUsers.GetByIds(userIds)).ToList(); - } - - public QuestionStat GetQuestionStats(long questionId) - { - using (var redis = RedisManager.GetReadOnlyClient()) - { - var result = new QuestionStat - { - VotesUpCount = redis.GetSetCount(QuestionUserIndex.UpVotes(questionId)), - VotesDownCount = redis.GetSetCount(QuestionUserIndex.DownVotes(questionId)) - }; - result.VotesTotal = result.VotesUpCount - result.VotesDownCount; - return result; - } - } - - public List GetTagsByPopularity(int skip, int take) - { - using (var redis = RedisManager.GetReadOnlyClient()) - { - var tagEntries = redis.GetRangeWithScoresFromSortedSetDesc(TagIndex.All, skip, take); - var tags = tagEntries.ConvertAll(kvp => new Tag { Name = kvp.Key, Score = (int)kvp.Value }); - return tags; - } - } - - public SiteStats GetSiteStats() - { - using (var redis = RedisManager.GetClient()) - { - return new SiteStats - { - QuestionsCount = redis.As().TypeIdsSet.Count, - AnswersCount = redis.As().TypeIdsSet.Count, - TopTags = GetTagsByPopularity(0, 10) - }; - } - } - } + public class Repository : IRepository + { + //Definition of all the redis keys that are used for indexes + static class TagIndex + { + public static string Questions(string tag) { return "urn:tags>q:" + tag.ToLower(); } + public static string All { get { return "urn:tags"; } } + } + + static class QuestionUserIndex + { + public static string UpVotes(long questionId) { return "urn:q>user+:" + questionId; } + public static string DownVotes(long questionId) { return "urn:q>user-:" + questionId; } + } + + static class UserQuestionIndex + { + public static string Questions(long userId) { return "urn:user>q:" + userId; } + public static string UpVotes(long userId) { return "urn:user>q+:" + userId; } + public static string DownVotes(long userId) { return "urn:user>q-:" + userId; } + } + + static class AnswerUserIndex + { + public static string UpVotes(long answerId) { return "urn:a>user+:" + answerId; } + public static string DownVotes(long answerId) { return "urn:a>user-:" + answerId; } + } + + static class UserAnswerIndex + { + public static string Answers(long userId) { return "urn:user>a:" + userId; } + public static string UpVotes(long userId) { return "urn:user>a+:" + userId; } + public static string DownVotes(long userId) { return "urn:user>a-:" + userId; } + } + + /// + /// Gets or sets the Redis Manager. The built-in IoC used with ServiceStack autowires this property. + /// + IRedisClientsManager RedisManager { get; set; } + + public Repository(IRedisClientsManager redisManager) + { + RedisManager = redisManager; + } + + public User GetOrCreateUser(User user) + { + if (user.DisplayName.IsNullOrEmpty()) + throw new ArgumentNullException("DisplayName"); + + var userIdAliasKey = "id:User:DisplayName:" + user.DisplayName.ToLower(); + + using (var redis = RedisManager.GetClient()) + { + //Get a typed version of redis client that works with + var redisUsers = redis.As(); + + //Find user by DisplayName if exists + var userKey = redis.GetValue(userIdAliasKey); + if (userKey != null) + return redisUsers.GetValue(userKey); + + //Generate Id for New User + if (user.Id == default(long)) + user.Id = redisUsers.GetNextSequence(); + + redisUsers.Store(user); + + //Save reference to User key using the DisplayName alias + redis.SetValue(userIdAliasKey, user.CreateUrn()); + + return redisUsers.GetById(user.Id); + } + } + + public UserStat GetUserStats(long userId) + { + using (var redis = RedisManager.GetClient()) + { + return new UserStat + { + UserId = userId, + QuestionsCount = redis.GetSetCount(UserQuestionIndex.Questions(userId)), + AnswersCount = redis.GetSetCount(UserAnswerIndex.Answers(userId)), + }; + } + } + + public List GetAllQuestions() + { + return RedisManager.ExecAs(redisQuestions => redisQuestions.GetAll()).ToList(); + } + + public List GetRecentQuestionResults(int skip, int take) + { + using (var redis = RedisManager.GetReadOnlyClient()) + { + return ToQuestionResults(redis.As().GetLatestFromRecentsList(skip, take)); + } + } + + public List GetQuestionsByUser(long userId) + { + using (var redis = RedisManager.GetReadOnlyClient()) + { + var questionIds = redis.GetAllItemsFromSet(UserQuestionIndex.Questions(userId)); + var questions = redis.As().GetByIds(questionIds); + return ToQuestionResults(questions); + } + } + + public List GetQuestionsTaggedWith(string tagName) + { + using (var redis = RedisManager.GetReadOnlyClient()) + { + var questionIds = redis.GetAllItemsFromSet(TagIndex.Questions(tagName)); + var questions = redis.As().GetByIds(questionIds); + return ToQuestionResults(questions); + } + } + + private List ToQuestionResults(IEnumerable questions) + { + var uniqueUserIds = questions.Map(x => x.UserId).ToHashSet(); + var usersMap = GetUsersByIds(uniqueUserIds).ToDictionary(x => x.Id); + + var results = questions.Map(x => new QuestionResult { Question = x }); + var resultsMap = results.ToDictionary(q => q.Question.Id); + + results.ForEach(x => x.User = usersMap[x.Question.UserId]); + + //Batch multiple operations in a single pipelined transaction (i.e. for a single network request/response) + RedisManager.ExecTrans(trans => + { + foreach (var question in questions) + { + var q = question; + + trans.QueueCommand(r => r.GetSetCount(QuestionUserIndex.UpVotes(q.Id)), + voteUpCount => resultsMap[q.Id].VotesUpCount = voteUpCount); + + trans.QueueCommand(r => r.GetSetCount(QuestionUserIndex.DownVotes(q.Id)), + voteDownCount => resultsMap[q.Id].VotesDownCount = voteDownCount); + + trans.QueueCommand(r => r.As().GetRelatedEntitiesCount(q.Id), + answersCount => resultsMap[q.Id].AnswersCount = answersCount); + } + }); + + return results; + } + + /// + /// Delete question by performing compensating actions to StoreQuestion() to keep the datastore in a consistent state + /// + /// + public void DeleteQuestion(long questionId) + { + using (var redis = RedisManager.GetClient()) + { + var redisQuestions = redis.As(); + + var question = redisQuestions.GetById(questionId); + if (question == null) return; + + //decrement score in tags list + question.Tags.ForEach(tag => redis.IncrementItemInSortedSet(TagIndex.All, tag, -1)); + + //remove all related answers + redisQuestions.DeleteRelatedEntities(questionId); + + //remove this question from user index + redis.RemoveItemFromSet(UserQuestionIndex.Questions(question.UserId), questionId.ToString()); + + //remove tag => questions index for each tag + question.Tags.ForEach(tag => redis.RemoveItemFromSet(TagIndex.Questions(tag), questionId.ToString())); + + redisQuestions.DeleteById(questionId); + } + } + + public void StoreQuestion(Question question) + { + using (var redis = RedisManager.GetClient()) + { + var redisQuestions = redis.As(); + + if (question.Tags == null) question.Tags = new List(); + if (question.Id == default(long)) + { + question.Id = redisQuestions.GetNextSequence(); + question.CreatedDate = DateTime.UtcNow; + + //Increment the popularity for each new question tag + question.Tags.ForEach(tag => redis.IncrementItemInSortedSet(TagIndex.All, tag, 1)); + } + + redisQuestions.Store(question); + redisQuestions.AddToRecentsList(question); + redis.AddItemToSet(UserQuestionIndex.Questions(question.UserId), question.Id.ToString()); + + //Populate tag => questions index for each tag + question.Tags.ForEach(tag => redis.AddItemToSet(TagIndex.Questions(tag), question.Id.ToString())); + } + } + + /// + /// Delete Answer by performing compensating actions to StoreAnswer() to keep the datastore in a consistent state + /// + /// + /// + public void DeleteAnswer(long questionId, long answerId) + { + using (var redis = RedisManager.GetClient()) + { + var answer = redis.As().GetRelatedEntities(questionId).FirstOrDefault(x => x.Id == answerId); + if (answer == null) return; + + redis.As().DeleteRelatedEntity(questionId, answerId); + + //remove user => answer index + redis.RemoveItemFromSet(UserAnswerIndex.Answers(answer.UserId), answerId.ToString()); + } + } + + public void StoreAnswer(Answer answer) + { + using (var redis = RedisManager.GetClient()) + { + if (answer.Id == default(long)) + { + answer.Id = redis.As().GetNextSequence(); + answer.CreatedDate = DateTime.UtcNow; + } + + //Store as a 'Related Answer' to the parent Question + redis.As().StoreRelatedEntities(answer.QuestionId, answer); + //Populate user => answer index + redis.AddItemToSet(UserAnswerIndex.Answers(answer.UserId), answer.Id.ToString()); + } + } + + public List GetAnswersForQuestion(long questionId) + { + using (var redis = RedisManager.GetClient()) + { + return redis.As().GetRelatedEntities(questionId); + } + } + + public void VoteQuestionUp(long userId, long questionId) + { + //Populate Question => User and User => Question set indexes in a single transaction + RedisManager.ExecTrans(trans => + { + //Register upvote against question and remove any downvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(QuestionUserIndex.UpVotes(questionId), userId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(QuestionUserIndex.DownVotes(questionId), userId.ToString())); + + //Register upvote against user and remove any downvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(UserQuestionIndex.UpVotes(userId), questionId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(UserQuestionIndex.DownVotes(userId), questionId.ToString())); + }); + } + + public void VoteQuestionDown(long userId, long questionId) + { + //Populate Question => User and User => Question set indexes in a single transaction + RedisManager.ExecTrans(trans => + { + //Register downvote against question and remove any upvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(QuestionUserIndex.DownVotes(questionId), userId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(QuestionUserIndex.UpVotes(questionId), userId.ToString())); + + //Register downvote against user and remove any upvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(UserQuestionIndex.DownVotes(userId), questionId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(UserQuestionIndex.UpVotes(userId), questionId.ToString())); + }); + } + + public void VoteAnswerUp(long userId, long answerId) + { + //Populate Question => User and User => Question set indexes in a single transaction + RedisManager.ExecTrans(trans => + { + //Register upvote against answer and remove any downvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(AnswerUserIndex.UpVotes(answerId), userId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(AnswerUserIndex.DownVotes(answerId), userId.ToString())); + + //Register upvote against user and remove any downvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(UserAnswerIndex.UpVotes(userId), answerId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(UserAnswerIndex.DownVotes(userId), answerId.ToString())); + }); + } + + public void VoteAnswerDown(long userId, long answerId) + { + //Populate Question => User and User => Question set indexes in a single transaction + RedisManager.ExecTrans(trans => + { + //Register downvote against answer and remove any upvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(AnswerUserIndex.DownVotes(answerId), userId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(AnswerUserIndex.UpVotes(answerId), userId.ToString())); + + //Register downvote against user and remove any upvotes if any + trans.QueueCommand(redis => redis.AddItemToSet(UserAnswerIndex.DownVotes(userId), answerId.ToString())); + trans.QueueCommand(redis => redis.RemoveItemFromSet(UserAnswerIndex.UpVotes(userId), answerId.ToString())); + }); + } + + public QuestionResult GetQuestion(long questionId) + { + var question = RedisManager.ExecAs(redisQuestions => redisQuestions.GetById(questionId)); + if (question == null) return null; + + var result = ToQuestionResults(new[] { question })[0]; + var answers = GetAnswersForQuestion(questionId); + var uniqueUserIds = answers.ConvertAll(x => x.UserId).ToHashSet(); + var usersMap = GetUsersByIds(uniqueUserIds).ToDictionary(x => x.Id); + + result.Answers = answers.ConvertAll(answer => + new AnswerResult { Answer = answer, User = usersMap[answer.UserId] }); + + return result; + } + + public List GetUsersByIds(IEnumerable userIds) + { + return RedisManager.ExecAs(redisUsers => redisUsers.GetByIds(userIds)).ToList(); + } + + public QuestionStat GetQuestionStats(long questionId) + { + using (var redis = RedisManager.GetReadOnlyClient()) + { + var result = new QuestionStat + { + VotesUpCount = redis.GetSetCount(QuestionUserIndex.UpVotes(questionId)), + VotesDownCount = redis.GetSetCount(QuestionUserIndex.DownVotes(questionId)) + }; + result.VotesTotal = result.VotesUpCount - result.VotesDownCount; + return result; + } + } + + public List GetTagsByPopularity(int skip, int take) + { + using (var redis = RedisManager.GetReadOnlyClient()) + { + var tagEntries = redis.GetRangeWithScoresFromSortedSetDesc(TagIndex.All, skip, take); + var tags = tagEntries.Map(kvp => new Tag { Name = kvp.Key, Score = (int)kvp.Value }); + return tags; + } + } + + public SiteStats GetSiteStats() + { + using (var redis = RedisManager.GetClient()) + { + return new SiteStats + { + QuestionsCount = redis.As().TypeIdsSet.Count, + AnswersCount = redis.As().TypeIdsSet.Count, + TopTags = GetTagsByPopularity(0, 10) + }; + } + } + } } \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionService.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionService.cs deleted file mode 100644 index bab7c798..00000000 --- a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionService.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface; -using ServiceStack.ServiceInterface.ServiceModel; - -namespace RedisStackOverflow.ServiceInterface -{ - [DataContract] - [RestService("/questions", "POST")] - [RestService("/questions/{Id}")] - public class Question - { - public Question() - { - this.Tags = new List(); - } - - [DataMember] - public long Id { get; set; } - - [DataMember] - public long UserId { get; set; } - - [DataMember] - public string Title { get; set; } - - [DataMember] - public string Content { get; set; } - - [DataMember] - public DateTime CreatedDate { get; set; } - - [DataMember] - public List Tags { get; set; } - } - - [DataContract] - public class Answer - { - [DataMember] - public long Id { get; set; } - - [DataMember] - public long QuestionId { get; set; } - - [DataMember] - public long UserId { get; set; } - - [DataMember] - public DateTime CreatedDate { get; set; } - - [DataMember] - public string Content { get; set; } - } - - [DataContract] - public class AnswerResult - { - [DataMember] - public Answer Answer { get; set; } - - [DataMember] - public User User { get; set; } - } - - [DataContract] - public class QuestionResponse : IHasResponseStatus - { - [DataMember] - public QuestionResult Result { get; set; } - - //For automatic injection of service exceptions - [DataMember] public ResponseStatus ResponseStatus { get; set; } - } - - public class QuestionService - : RestServiceBase - { - public IRepository Repository { get; set; } - - public override object OnGet(Question question) - { - return new QuestionResponse - { - Result = Repository.GetQuestion(question.Id), - }; - } - - public override object OnPost(Question question) - { - Repository.StoreQuestion(question); - return new QuestionResponse(); - } - - public override object OnDelete(Question request) - { - Repository.DeleteQuestion(request.Id); - - return new QuestionResponse(); - } - } -} \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionStatService.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionStatService.cs deleted file mode 100644 index 6ad4a2cf..00000000 --- a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionStatService.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Runtime.Serialization; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface; - -namespace RedisStackOverflow.ServiceInterface -{ - [DataContract] - [RestService("/questions/{QuestionId}/stats")] - public class QuestionStats - { - [DataMember] - public long QuestionId { get; set; } - } - - [DataContract] - public class QuestionStat - { - [DataMember] - public int VotesUpCount { get; set; } - - [DataMember] - public int VotesDownCount { get; set; } - - [DataMember] - public int VotesTotal { get; set; } - } - - [DataContract] - public class QuestionStatsResponse - { - [DataMember] - public QuestionStat Result { get; set; } - } - - public class QuestionStatService - : RestServiceBase - { - public IRepository Repository { get; set; } - - public override object OnPost(QuestionStats request) - { - return new QuestionStatsResponse - { - Result = Repository.GetQuestionStats(request.QuestionId) - }; - } - } -} \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionsService.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionsService.cs index 5f61ea48..a0bfc4e9 100644 --- a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionsService.cs +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/QuestionsService.cs @@ -1,86 +1,52 @@ -using System.Collections.Generic; -using System.Runtime.Serialization; -using ServiceStack.Common.Extensions; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface; -using ServiceStack.ServiceInterface.ServiceModel; +using RedisStackOverflow.ServiceModel; +using ServiceStack; namespace RedisStackOverflow.ServiceInterface { - [RestService("/questions", "GET")] - [RestService("/questions/page/{Page}")] - [RestService("/questions/tagged/{Tag}")] - [RestService("/users/{UserId}/questions")] - [DataContract] - public class Questions - { - [DataMember] - public int? Page { get; set; } - - [DataMember] - public string Tag { get; set; } - - [DataMember] - public long? UserId { get; set; } - } - - [DataContract] - public class QuestionsResponse - { - public QuestionsResponse() - { - this.ResponseStatus = new ResponseStatus(); - } - - [DataMember] - public List Results { get; set; } - - //For automatic injection of service exceptions - [DataMember] public ResponseStatus ResponseStatus { get; set; } - } - - [DataContract] - public class QuestionResult - { - public QuestionResult() - { - this.Answers = new List(); - } - - [DataMember] - public Question Question { get; set; } - - [DataMember] - public User User { get; set; } - - [DataMember] - public int AnswersCount { get; set; } - - [DataMember] - public int VotesUpCount { get; set; } - - [DataMember] - public int VotesDownCount { get; set; } - - [DataMember] - public List Answers { get; set; } - } - - public class QuestionsService - : RestServiceBase - { - public IRepository Repository { get; set; } - - public override object OnGet(Questions request) - { - if (!request.Tag.IsNullOrEmpty()) - return new QuestionsResponse { Results = Repository.GetQuestionsTaggedWith(request.Tag) }; - - if (request.UserId.HasValue) - return new QuestionsResponse { Results = Repository.GetQuestionsByUser(request.UserId.Value) }; - - var pageOffset = request.Page.GetValueOrDefault(0) * 10; - return new QuestionsResponse { Results = Repository.GetRecentQuestionResults(pageOffset, pageOffset + 10) }; - } - } + /// + /// Create your ServiceStack rest-ful web service implementation. + /// + public class QuestionsService : Service + { + /// + /// Gets or sets the repository. The built-in IoC used with ServiceStack autowires this property. + /// + public IRepository Repository { get; set; } + + public object Get(Questions request) + { + if (!request.Tag.IsNullOrEmpty()) + return new QuestionsResponse { Results = Repository.GetQuestionsTaggedWith(request.Tag) }; + + if (request.UserId.HasValue) + return new QuestionsResponse { Results = Repository.GetQuestionsByUser(request.UserId.Value) }; + + var pageOffset = request.Page.GetValueOrDefault(0) * 10; + return new QuestionsResponse { Results = Repository.GetRecentQuestionResults(pageOffset, pageOffset + 10) }; + } + + public object Get(Question question) + { + return new QuestionResponse { + Result = Repository.GetQuestion(question.Id), + }; + } + + public void Post(Question question) + { + Repository.StoreQuestion(question); + } + + public void Delete(Question request) + { + Repository.DeleteQuestion(request.Id); + } + + public object Post(QuestionStats request) + { + return new QuestionStatsResponse { + Result = Repository.GetQuestionStats(request.QuestionId) + }; + } + } } \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/RedisStackOverflow.ServiceInterface.csproj b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/RedisStackOverflow.ServiceInterface.csproj index 506a6b6f..3ff814da 100644 --- a/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/RedisStackOverflow.ServiceInterface.csproj +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/RedisStackOverflow.ServiceInterface.csproj @@ -10,7 +10,7 @@ Properties RedisStackOverflow.ServiceInterface RedisStackOverflow.ServiceInterface - v3.5 + v4.5 512 @@ -31,6 +31,7 @@ false false true + true @@ -41,6 +42,7 @@ prompt 4 AllRules.ruleset + false pdbonly @@ -50,37 +52,41 @@ prompt 4 AllRules.ruleset + false - - ..\..\..\lib\ServiceStack.dll + + ..\..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True - - ..\..\..\lib\ServiceStack.Common.dll + + ..\..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True - - False - ..\..\..\lib\ServiceStack.Interfaces.dll + + ..\..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True - - ..\..\..\lib\ServiceStack.Redis.dll + + ..\..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True - - False - ..\..\..\lib\ServiceStack.ServiceInterface.dll + + ..\..\packages\ServiceStack.Redis.4.5.0\lib\net45\ServiceStack.Redis.dll + True + + + ..\..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True - 3.5 - 3.0 - 3.5 - 3.5 @@ -88,15 +94,11 @@ - - - - @@ -115,6 +117,15 @@ true + + + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14} + RedisStackOverflow.ServiceModel + + + + + + \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Reset.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Reset.cs new file mode 100644 index 00000000..5fdfef62 --- /dev/null +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Reset.cs @@ -0,0 +1,28 @@ +using ServiceStack; + +namespace RedisStackOverflow.ServiceModel +{ + /// + /// Define your ServiceStack web service request (i.e. the Request DTO). + /// + [Route("/reset")] + public class Reset { } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + public class ResetResponse : IHasResponseStatus + { + public ResetResponse() + { + //Comment this out if you wish to receive the response status. + this.ResponseStatus = new ResponseStatus(); + } + + /// + /// Gets or sets the ResponseStatus. The built-in Ioc used with ServiceStack autowires this property with service exceptions. + /// + public ResponseStatus ResponseStatus { get; set; } + } + +} \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Stats.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Stats.cs new file mode 100644 index 00000000..0ab4fe7d --- /dev/null +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Stats.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using ServiceStack; + +namespace RedisStackOverflow.ServiceModel +{ + /// + /// Define your ServiceStack web service request (i.e. the Request DTO). + /// + [Route("/stats")] + public class Stats { } + + public class SiteStats + { + public SiteStats() + { + this.TopTags = new List(); + } + + public int QuestionsCount { get; set; } + public int AnswersCount { get; set; } + public List TopTags { get; set; } + } + + public class Tag + { + public string Name { get; set; } + public int Score { get; set; } + } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + public class StatsResponse + { + public SiteStats Result { get; set; } + } + +} \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Users.cs b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Users.cs new file mode 100644 index 00000000..f087675e --- /dev/null +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/Users.cs @@ -0,0 +1,65 @@ +using ServiceStack; + +namespace RedisStackOverflow.ServiceModel +{ + /// + /// Define your ServiceStack web service request (i.e. the Request DTO). + /// + [Route("/users")] + public class User + { + public long Id { get; set; } + public string DisplayName { get; set; } + } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + public class UserResponse + { + public User Result { get; set; } + } + + + /// + /// Define your ServiceStack web service request (i.e. the Request DTO). + /// + [Route("/users/{UserId}/stats")] + public class UserStats + { + public long UserId { get; set; } + } + + public class UserStat + { + public long UserId { get; set; } + public long QuestionsCount { get; set; } + public long AnswersCount { get; set; } + } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + public class UserStatsResponse + { + public UserStat Result { get; set; } + } + + /// + /// Define your ServiceStack web service request (i.e. the Request DTO). + /// + [Route("/users/{UserId}/questionvotes/{QuestionId}")] + [Route("/users/{UserId}/answervotes/{AnswerId}")] + public class UserVotes + { + public long UserId { get; set; } + public long? QuestionId { get; set; } + public long? AnswerId { get; set; } + public string Direction { get; set; } + } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + public class UserVotesResponse { } +} \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/packages.config b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/packages.config new file mode 100644 index 00000000..5c87f865 --- /dev/null +++ b/src/RedisStackOverflow/RedisStackOverflow.ServiceModel/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow.sln b/src/RedisStackOverflow/RedisStackOverflow.sln index a371072f..22b930e6 100644 --- a/src/RedisStackOverflow/RedisStackOverflow.sln +++ b/src/RedisStackOverflow/RedisStackOverflow.sln @@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStackOverflow.ServiceI EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStackOverflow", "RedisStackOverflow\RedisStackOverflow.csproj", "{CCAC74EA-08EE-41A8-BF01-8F1B7D207144}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedisStackOverflow.ServiceModel", "RedisStackOverflow.ServiceModel\RedisStackOverflow.ServiceModel.csproj", "{BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -19,6 +21,10 @@ Global {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Debug|Any CPU.Build.0 = Debug|Any CPU {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|Any CPU.ActiveCfg = Release|Any CPU {CCAC74EA-08EE-41A8-BF01-8F1B7D207144}.Release|Any CPU.Build.0 = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/RedisStackOverflow/RedisStackOverflow/default.css b/src/RedisStackOverflow/RedisStackOverflow/Content/Css/default.css similarity index 89% rename from src/RedisStackOverflow/RedisStackOverflow/default.css rename to src/RedisStackOverflow/RedisStackOverflow/Content/Css/default.css index 907105cd..65216bf3 100644 --- a/src/RedisStackOverflow/RedisStackOverflow/default.css +++ b/src/RedisStackOverflow/RedisStackOverflow/Content/Css/default.css @@ -1,6 +1,6 @@ BODY { - background: #fff url(img/bg-body-1024.png) repeat-y top left; + background: #fff url(../Images/bg-body-1024.png) repeat-y top left; font: normal normal normal 13.34px/normal helvetica, arial, freesans, clean, sans-serif; padding: 0 5px 20px 10px; width: 940px; @@ -79,7 +79,7 @@ INPUT[type=text] } H1 A { - background: url(http://www.servicestack.net/logo-servicestack.png) no-repeat; + background: url(http://mono.servicestack.net/logo-servicestack.png) no-repeat; display: block; height: 38px; padding: 70px 30px 0 120px; @@ -111,12 +111,12 @@ H4 FORM { - display: none; + display: none; } BUTTON { - padding: 5px 10px; + padding: 5px 10px; } @@ -246,10 +246,10 @@ H4 EM } .del { - width: 16px; - height: 16px; - float: right; - background: url(img/delete_icon.png) no-repeat; + width: 16px; + height: 16px; + float: right; + background: url(../Images/delete_icon.png) no-repeat; } .by @@ -329,16 +329,16 @@ H4 EM cursor:pointer; } .question-votes B.up { - background: url(img/vote-up.png) no-repeat 50% bottom; + background: url(../Images/vote-up.png) no-repeat 50% bottom; } .question-votes B.down { - background: url(img/vote-down.png) no-repeat 50% top; + background: url(../Images/vote-down.png) no-repeat 50% top; } .question-votes B.up.user-selected { - background: url(img/myvote-up.png) no-repeat 50% bottom; + background: url(../Images/myvote-up.png) no-repeat 50% bottom; } .question-votes B.down.user-selected { - background: url(img/myvote-down.png) no-repeat 50% bottom; + background: url(../Images/myvote-down.png) no-repeat 50% bottom; } .question-content { @@ -434,15 +434,15 @@ H4 EM } #trivia { - margin: 3px 0 0 0; - padding: 1px 4px; - color: #444; - font-size: 12px; - background: #f1f1f1; + margin: 3px 0 0 0; + padding: 1px 4px; + color: #444; + font-size: 12px; + background: #f1f1f1; } #trivia B { - color: #333; + color: #333; } #footer { @@ -454,5 +454,4 @@ H4 EM border-top: solid 1px #999; background: #f1f1f1; padding: 10px; -} - +} \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/Mono-powered-big.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/Mono-powered-big.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/Mono-powered-big.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/Mono-powered-big.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/arrow-down.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/arrow-down.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/arrow-down.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/arrow-down.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/arrow-left.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/arrow-left.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/arrow-left.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/arrow-left.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/bg-body-1024.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/bg-body-1024.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/bg-body-1024.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/bg-body-1024.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/btn-github.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/btn-github.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/btn-github.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/btn-github.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/delete_icon.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/delete_icon.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/delete_icon.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/delete_icon.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/myvote-down.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/myvote-down.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/myvote-down.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/myvote-down.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/myvote-up.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/myvote-up.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/myvote-up.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/myvote-up.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/vote-down.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/vote-down.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/vote-down.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/vote-down.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/img/vote-up.png b/src/RedisStackOverflow/RedisStackOverflow/Content/Images/vote-up.png similarity index 100% rename from src/RedisStackOverflow/RedisStackOverflow/img/vote-up.png rename to src/RedisStackOverflow/RedisStackOverflow/Content/Images/vote-up.png diff --git a/src/RedisStackOverflow/RedisStackOverflow/Global.asax.cs b/src/RedisStackOverflow/RedisStackOverflow/Global.asax.cs index 9dd94044..e42da2be 100644 --- a/src/RedisStackOverflow/RedisStackOverflow/Global.asax.cs +++ b/src/RedisStackOverflow/RedisStackOverflow/Global.asax.cs @@ -1,33 +1,47 @@ using System; using Funq; using RedisStackOverflow.ServiceInterface; +using ServiceStack; +using ServiceStack.Configuration; +using ServiceStack.Logging; using ServiceStack.Redis; -using ServiceStack.WebHost.Endpoints; +using IRepository = RedisStackOverflow.ServiceInterface.IRepository; namespace RedisStackOverflow { - public class AppHost - : AppHostBase - { - public AppHost() - : base("Redis StackOverflow", typeof(QuestionsService).Assembly) { } + /// + /// Create your ServiceStack web service application with a singleton AppHost. + /// + public class AppHost : AppHostBase + { + /// + /// Initializes a new instance of your ServiceStack application, with the specified name and assembly containing the services. + /// + public AppHost() : base("Redis StackOverflow", typeof(QuestionsService).Assembly) { } - public override void Configure(Container container) - { - //Show StackTrace in Web Service Exceptions - SetConfig(new EndpointHostConfig { DebugMode = true }); - - //Register any dependencies you want injected into your services - container.Register(c => new PooledRedisClientManager()); - container.Register(c => new Repository(c.Resolve())); - } - } + /// + /// Configure the container with the necessary routes for your ServiceStack application. + /// + /// The built-in IoC used with ServiceStack. + public override void Configure(Container container) + { + //Show StackTrace in Web Service Exceptions + SetConfig(new HostConfig { DebugMode = true }); - public class Global : System.Web.HttpApplication - { - protected void Application_Start(object sender, EventArgs e) - { - new AppHost().Init(); - } - } + //Register any dependencies you want injected into your services + container.Register(c => new PooledRedisClientManager()); + container.Register(c => new Repository(c.Resolve())); + } + } + + public class Global : System.Web.HttpApplication + { + protected void Application_Start(object sender, EventArgs e) + { + if (ConfigUtils.GetAppSetting("log", false)) { LogManager.LogFactory = new ConsoleLogFactory(); } + + //Initialize your application + (new AppHost()).Init(); + } + } } \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow/RedisStackOverflow.csproj b/src/RedisStackOverflow/RedisStackOverflow/RedisStackOverflow.csproj index 48a95670..f109ef04 100644 --- a/src/RedisStackOverflow/RedisStackOverflow/RedisStackOverflow.csproj +++ b/src/RedisStackOverflow/RedisStackOverflow/RedisStackOverflow.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -11,12 +12,19 @@ Properties RedisStackOverflow RedisStackOverflow - v3.5 + v4.5 4.0 + false + + + + + + true @@ -27,6 +35,7 @@ prompt 4 AllRules.ruleset + false pdbonly @@ -36,58 +45,62 @@ prompt 4 AllRules.ruleset + false - - ..\..\..\lib\ServiceStack.dll + + ..\..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True - - ..\..\..\lib\ServiceStack.Common.dll + + ..\..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True - - ..\..\..\lib\ServiceStack.Interfaces.dll + + ..\..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True - - ..\..\..\lib\ServiceStack.Redis.dll + + ..\..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True - - ..\..\..\lib\ServiceStack.ServiceInterface.dll + + ..\..\packages\ServiceStack.Redis.4.5.0\lib\net45\ServiceStack.Redis.dll + True + + + ..\..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True - - 3.5 - - - 3.5 - - - 3.5 - - - 3.5 - + + + + + + - + - - - - - - - - - - + + + + + + + + + + Designer @@ -103,12 +116,24 @@ {41C8C157-B2A4-4DDE-B153-233E46109F39} RedisStackOverflow.ServiceInterface + + {BFAB0E32-43F3-4A0E-9409-FC57FCF4BF14} + RedisStackOverflow.ServiceModel + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + - + + - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/RedisStackOverflow/RedisStackOverflow/default.htm b/src/RedisStackOverflow/RedisStackOverflow/default.htm index dfce899a..50885ffb 100644 --- a/src/RedisStackOverflow/RedisStackOverflow/default.htm +++ b/src/RedisStackOverflow/RedisStackOverflow/default.htm @@ -3,7 +3,7 @@ ServiceStack Redis StackOverflow - + - + REST Files: GitHub-like file access with 1 page jQuery + 1 C# REST Service + + + + - -ServiceStack Home - - diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Soap12.aspx.cs b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Soap12.aspx.cs index 401d2e18..a4694a9d 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Soap12.aspx.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Soap12.aspx.cs @@ -3,152 +3,157 @@ using System.Linq; using System.ServiceModel; using System.Text; -using ServiceStack.Common.Extensions; using ServiceStack.Examples.Clients.Soap12ServiceReference; namespace ServiceStack.Examples.Clients { - public partial class Soap12 : System.Web.UI.Page - { - private const string EndpointUri = "http://localhost/ServiceStack.Examples.Host.Web/ServiceStack/Soap12"; - - private readonly SyncReplyClient client; - - //Generated proxy when using 'Add Service Reference' on the EndpointUri above. - //Thank WCF for the config ugliness - - public Soap12() - { - var binding = new WSHttpBinding - { - MaxReceivedMessageSize = int.MaxValue, - HostNameComparisonMode = HostNameComparisonMode.StrongWildcard, - MaxBufferPoolSize = 524288, - }; - binding.Security.Mode = SecurityMode.None; - - client = new SyncReplyClient( - binding, - new EndpointAddress(EndpointUri)); - } - - protected void Page_Load(object sender, EventArgs e) - { - } - - protected void btnGetFactorial_Click(object sender, EventArgs e) - { - litGetFactorialResult.Text = litGetFactorialError.Text = ""; - try - { - var longValue = long.Parse(txtGetFactorial.Text); - var result = client.GetFactorial(longValue); - litGetFactorialResult.Text = result.ToString(); - } - catch (Exception ex) - { - litGetFactorialError.Text = ex.Message; - } - } - - protected void btnGetFibonacci_Click(object sender, EventArgs e) - { - litGetFibonacciResult.Text = litGetFibonacciError.Text = ""; - try - { - var skipValue = long.Parse(txtGetFibonacciSkip.Text); - var takeValue = long.Parse(txtGetFibonacciTake.Text); - var results = client.GetFibonacciNumbers(skipValue, takeValue); - - litGetFibonacciResult.Text = string.Join(", ", results.ConvertAll(x => x.ToString()).ToArray()); - } - catch (Exception ex) - { - litGetFibonacciError.Text = ex.Message; - } - } - - protected void btnStoreNewUser_Click(object sender, EventArgs e) - { - litStoreNewUserResult.Text = litStoreNewUserError.Text = ""; - try - { - long userIdResult; - var responseStatus = client.StoreNewUser(out userIdResult, - txtStoreNewUserEmail.Text, - txtStoreNewUserPassword.Text, - txtStoreNewUserUsername.Text); - - if (responseStatus.ErrorCode != null) - { - litStoreNewUserError.Text = responseStatus.ErrorCode.ToEnglish(); - return; - } - - litStoreNewUserResult.Text = "New User Id: " + userIdResult; - var userIds = new List(txtGetUsersUserIds.Text.Split(',')) - { - userIdResult.ToString() - }.Where(x => !string.IsNullOrEmpty(x.Trim())); - - txtGetUsersUserIds.Text = string.Join(",", userIds.ToArray()); - } - catch (Exception ex) - { - litStoreNewUserError.Text = ex.Message; - } - } - - protected void btnDeleteAllUsers_Click(object sender, EventArgs e) - { - litStoreNewUserResult.Text = litStoreNewUserError.Text = ""; - try - { - long userIdResult; - client.DeleteAllUsers(out userIdResult); - - litStoreNewUserResult.Text = "All users were deleted."; - } - catch (Exception ex) - { - litStoreNewUserError.Text = ex.Message; - } - } - - protected void btnGetUsers_Click(object sender, EventArgs e) - { - litGetUsersResult.Text = litGetUsersError.Text = ""; - try - { - User[] userResults; - var userIds = new List(txtGetUsersUserIds.Text.Split(',')) - .Where(x => !string.IsNullOrEmpty(x.Trim())) - .ConvertAll(x => long.Parse(x.Trim())).ToArray(); - - client.GetUsers(out userResults, userIds, null); - - if (userResults != null && userIds.Length > 0) - { - var sb = new StringBuilder(); - - foreach (var user in userResults) - { - sb.AppendFormat("
    {0}
    {1}
    \n", - user.UserName, user.Password); - } - - litGetUsersResult.Text = sb.ToString(); - } - else - { - litGetUsersResult.Text = "No matching users found."; - } - } - catch (Exception ex) - { - litGetUsersError.Text = ex.Message; - } - } - } + public partial class Soap12 : System.Web.UI.Page + { + private const string EndpointUri = "http://localhost:64067/ServiceStack/soap12"; + + private readonly SyncReplyClient client; + + //Generated proxy when using 'Add Service Reference' on the EndpointUri above. + //Thank WCF for the config ugliness + + public Soap12() + { + var binding = new WSHttpBinding + { + MaxReceivedMessageSize = int.MaxValue, + HostNameComparisonMode = HostNameComparisonMode.StrongWildcard, + MaxBufferPoolSize = 524288, + }; + binding.Security.Mode = SecurityMode.None; + + client = new SyncReplyClient( + binding, + new EndpointAddress(EndpointUri)); + } + + protected void Page_Load(object sender, EventArgs e) + { + } + + protected void btnGetFactorial_Click(object sender, EventArgs e) + { + litGetFactorialResult.Text = litGetFactorialError.Text = ""; + try + { + var longValue = long.Parse(txtGetFactorial.Text); + var result = client.GetFactorial(new GetFactorial { ForNumber = longValue }); + litGetFactorialResult.Text = result.ToString(); + } + catch (Exception ex) + { + litGetFactorialError.Text = ex.Message; + } + } + + protected void btnGetFibonacci_Click(object sender, EventArgs e) + { + litGetFibonacciResult.Text = litGetFibonacciError.Text = ""; + try + { + var skipValue = long.Parse(txtGetFibonacciSkip.Text); + var takeValue = long.Parse(txtGetFibonacciTake.Text); + var results = client.GetFibonacciNumbers(new GetFibonacciNumbers + { + Skip = skipValue, + Take = takeValue, + }).Results; + + litGetFibonacciResult.Text = string.Join(", ", results.ConvertAll(x => x.ToString()).ToArray()); + } + catch (Exception ex) + { + litGetFibonacciError.Text = ex.Message; + } + } + + protected void btnStoreNewUser_Click(object sender, EventArgs e) + { + litStoreNewUserResult.Text = litStoreNewUserError.Text = ""; + try + { + var response = client.StoreNewUser( + new StoreNewUser + { + Email = txtStoreNewUserEmail.Text, + UserName = txtStoreNewUserUsername.Text, + Password = txtStoreNewUserPassword.Text, + }); + + var userIdResult = response.UserId; + + if (response.ResponseStatus.ErrorCode != null) + { + litStoreNewUserError.Text = response.ResponseStatus.ErrorCode.ToEnglish(); + return; + } + + litStoreNewUserResult.Text = "New User Id: " + userIdResult; + var userIds = new List(txtGetUsersUserIds.Text.Split(',')) + { + userIdResult.ToString() + }.Where(x => !string.IsNullOrEmpty(x.Trim())); + + txtGetUsersUserIds.Text = string.Join(",", userIds.ToArray()); + } + catch (Exception ex) + { + litStoreNewUserError.Text = ex.Message; + } + } + + protected void btnDeleteAllUsers_Click(object sender, EventArgs e) + { + litStoreNewUserResult.Text = litStoreNewUserError.Text = ""; + try + { + client.DeleteAllUsers(new DeleteAllUsers()); + + litStoreNewUserResult.Text = "All users were deleted."; + } + catch (Exception ex) + { + litStoreNewUserError.Text = ex.Message; + } + } + + protected void btnGetUsers_Click(object sender, EventArgs e) + { + litGetUsersResult.Text = litGetUsersError.Text = ""; + try + { + var userIds = new List(txtGetUsersUserIds.Text.Split(',')) + .Where(x => !string.IsNullOrEmpty(x.Trim())) + .Map(x => long.Parse(x.Trim())).ToArray(); + + var userResults = client.GetUsers(new GetUsers { UserIds = userIds, }).Users; + + if (userResults != null && userIds.Length > 0) + { + var sb = new StringBuilder(); + + foreach (User user in userResults) + { + sb.AppendFormat("
    {0}
    {1}
    \n", + user.UserName, user.Password); + } + + litGetUsersResult.Text = sb.ToString(); + } + else + { + litGetUsersResult.Text = "No matching users found."; + } + } + catch (Exception ex) + { + litGetUsersError.Text = ex.Message; + } + } + } } diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Web.config b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Web.config index 2e767148..700cf7a3 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Web.config +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/Web.config @@ -1,44 +1,35 @@ - - - -
    - -
    -
    -
    -
    - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/default.htm b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/default.htm index 3fdf07b5..e074f64f 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/default.htm +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/default.htm @@ -1,612 +1,611 @@ - - - - ServiceStack Examples :: Ajax Client - - - - - - - - - - - - - - Service Stack Demo - -

    Calling ServiceStack Web Services with Ajax

    - -

    - For performance reasons, the preferred to call ServiceStack services for Ajax clients - is using JSON via the JSON endpoint at:
    - ~/ServiceStack/Json/SyncReply/{ServiceName} -

    -

    - As this endpoint is just a standard JSON service we can use any ajax client to call them with. - In this example we're using a light-wrapper around jQuery's $.ajax client. -

    - -

    1. First step is to initialize the ServiceClient

    - - //Create a ClientGateway passing in the baseUrl where your services are hosted. - var gateway = new servicestack.ClientGateway( - location.protocol + "//" + location.host + '/ServiceStack.Examples.Host.Web/ServiceStack/'); - - -

    2. After that calling a service becomes as easy as:

    - - gateway.getFromService({ - GetFactorial: { ForNumber: $("#txtGetFactorial").val() } - }, - function(e) { - $("#serviceGetFactorial .result").html(e.Result); - }); - - -

    3. Try the live examples yourself:

    -
    -
    - - - -
    -

    Get Factorial Service

    - - - -
    - -

    Result

    -
    -
    - -
    - - - -
    - -

    Get Fibonacci Numbers Service

    - - - - - - - - -
    - -

    Result

    -
    -
    - -
    - - - -
    -

    Store New User Service

    - -
    - - - - - - - - -
    - - -
    - -

    Result

    -
    - - -
    - -
    - - - -
    -

    Get Users Service

    - -
    - - -
    - - -
    - -

    Result

    -
    -
    - - -
    - -

    4. Check out the other ways to call your services

    -

    - One of the nice things about ServiceStack is that by using POCO classes to define your Service Interface - we're able to seperate the 'message' (payload) from the communication 'channel' that delivers it. -

    -

    - This means that calling your services using XML is as easy as sending your request to a different end point. - So calling your service via XML is as easy as: -

      -
    1. - ServiceStack/Xml/SyncReply/GetFactorial?ForNumber=3 -
    2. -
    3. - ServiceStack/Xml/SyncReply/GetFibonacciNumbers?Skip=3&Take=20 -
    4. -
    -
    - Out of the box ServiceStack provides REST+JSON, REST+XML and POX, SOAP 1.1 and SOAP 1.2 end points. -

    -

    - The dynamic metadata summary page - has a complete list of web services and end points that are available.
    -

    - -

    5. View the source code online or Download:

    -

    - The complete source code for this example is - - viewable online - - or available to download as zip package from the link below: - - - Download ServiceStack.Examples.zip - -

    - - - - - - - + + + + ServiceStack Examples :: Ajax Client + + + + + + + + + + + + + + Service Stack Demo + +

    Calling ServiceStack Web Services with Ajax

    + +

    + For performance reasons, the preferred to call ServiceStack services for Ajax clients + is using JSON via the JSON endpoint at:
    + ~/servicestack/json/reply/{ServiceName} +

    +

    + As this endpoint is just a standard JSON service we can use any ajax client to call them with. + In this example we're using a light-wrapper around jQuery's $.ajax client. +

    + +

    1. First step is to initialize the ServiceClient

    + + //Create a ClientGateway passing in the baseUrl where your services are hosted. + var gateway = new servicestack.ClientGateway( + location.protocol + "//" + location.host + '/ServiceStack.Examples.Host.Web/ServiceStack/'); + + +

    2. After that calling a service becomes as easy as:

    + + gateway.getFromService({ + GetFactorial: { ForNumber: $("#txtGetFactorial").val() } + }, + function(e) { + $("#serviceGetFactorial .result").html(e.Result); + }); + + +

    3. Try the live examples yourself:

    +
    +
    + + + +
    +

    Get Factorial Service

    + + + +
    + +

    Result

    +
    +
    + +
    + + + +
    + +

    Get Fibonacci Numbers Service

    + + + + + + + + +
    + +

    Result

    +
    +
    + +
    + + + +
    +

    Store New User Service

    + +
    + + + + + + + + +
    + + +
    + +

    Result

    +
    + + +
    + +
    + + + +
    +

    Get Users Service

    + +
    + + +
    + + +
    + +

    Result

    +
    +
    + + +
    + +

    4. Check out the other ways to call your services

    +

    + One of the nice things about ServiceStack is that by using POCO classes to define your Service Interface + we're able to seperate the 'message' (payload) from the communication 'channel' that delivers it. +

    +

    + This means that calling your services using XML is as easy as sending your request to a different end point. + So calling your service via XML is as easy as: +

      +
    1. + servicestack/xml/reply/GetFactorial?ForNumber=3 +
    2. +
    3. + servicestack/xml/reply/GetFibonacciNumbers?Skip=3&Take=20 +
    4. +
    +
    + Out of the box ServiceStack provides REST+JSON, REST+XML and POX, SOAP 1.1 and SOAP 1.2 end points. +

    +

    + The dynamic metadata summary page + has a complete list of web services and end points that are available.
    +

    + +

    5. View the source code online or Download:

    +

    + The complete source code for this example is + + viewable online + + or available to download as zip package from the link below: + + + Download ServiceStack.Examples.zip + +

    + + + + + + + diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/js/ServiceStack.js b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/js/ServiceStack.js index af171a06..aa49f6d6 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/js/ServiceStack.js +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/js/ServiceStack.js @@ -6,8 +6,8 @@ */ var servicestack = (function(){ var JSC = function(baseUri) { - this.baseSyncReplyUri = path.combine(baseUri, "Json/SyncReply"); - this.baseAsyncOneWayUri = path.combine(baseUri, "Json/AsyncOneWay"); + this.baseSyncReplyUri = path.combine(baseUri, "json/reply"); + this.baseAsyncOneWayUri = path.combine(baseUri, "json/oneway"); }; var P = JSC.prototype; /** diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/packages.config b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/packages.config new file mode 100644 index 00000000..6b7d575f --- /dev/null +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Clients/sqlite3.dll b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/sqlite3.dll new file mode 100644 index 00000000..2d241c4e Binary files /dev/null and b/src/ServiceStack.Examples/ServiceStack.Examples.Clients/sqlite3.dll differ diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/App.config b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/App.config index a4ca9b56..59c35533 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/App.config +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/App.config @@ -1,4 +1,4 @@ - + @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/AppHost.cs b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/AppHost.cs index e7c29cd1..b19d4a2e 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/AppHost.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/AppHost.cs @@ -1,14 +1,13 @@ using Funq; -using ServiceStack.Common.Utils; using ServiceStack.Configuration; +using ServiceStack.Data; using ServiceStack.Examples.ServiceInterface; using ServiceStack.Examples.ServiceInterface.Support; -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Logging; -using ServiceStack.Logging.Support.Logging; using ServiceStack.OrmLite; using ServiceStack.OrmLite.Sqlite; -using ServiceStack.WebHost.Endpoints; +using ExampleConfig = ServiceStack.Examples.ServiceInterface.ExampleConfig; namespace ServiceStack.Examples.Host.Console { @@ -30,21 +29,16 @@ public AppHost() public override void Configure(Container container) { //Signal advanced web browsers what HTTP Methods you accept - base.SetConfig(new EndpointHostConfig + base.SetConfig(new HostConfig { - GlobalResponseHeaders = - { - { "Access-Control-Allow-Origin", "*" }, - { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }, - }, - WsdlServiceNamespace = "http://www.servicestack.net/types", + DebugMode = true, }); - container.Register(new ConfigurationResourceManager()); + container.Register(new AppSettings()); - var appSettings = container.Resolve(); + var appSettings = container.Resolve(); - container.Register(c => new ExampleConfig(c.Resolve())); + container.Register(c => new ExampleConfig(c.Resolve())); var appConfig = container.Resolve(); container.Register(c => @@ -59,7 +53,7 @@ public override void Configure(Container container) } } - private static void DatabaseTest(IDbConnectionFactory connectionFactory) + private void DatabaseTest(IDbConnectionFactory connectionFactory) { ConfigureDatabase.Init(connectionFactory); @@ -69,11 +63,11 @@ private static void DatabaseTest(IDbConnectionFactory connectionFactory) UserName = "new UserName" }; - var storeHandler = new StoreNewUserService { ConnectionFactory = connectionFactory }; - storeHandler.Execute(storeRequest); + var storeHandler = Container.Resolve(); + storeHandler.Any(storeRequest); - var getAllHandler = new GetAllUsersService { ConnectionFactory = connectionFactory }; - var response = (GetAllUsersResponse)getAllHandler.Execute(new GetAllUsers()); + var getAllHandler = Container.Resolve(); + var response = (GetAllUsersResponse)getAllHandler.Any(new GetAllUsers()); var user = response.Users[0]; diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/ServiceStack.Examples.Host.Console.csproj b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/ServiceStack.Examples.Host.Console.csproj index 9ba24eaf..787b2c85 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/ServiceStack.Examples.Host.Console.csproj +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/ServiceStack.Examples.Host.Console.csproj @@ -10,7 +10,7 @@ Properties ServiceStack.Examples.Host.Console ServiceStack.Examples.Host.Console - v3.5 + v4.5 512 @@ -31,6 +31,7 @@ false false true + true @@ -40,8 +41,33 @@ DEBUG;TRACE prompt 4 + false + + x86 AllRules.ruleset + + + true + false + + + true + + + false + false + + + + + false + false + Default + false + + + false pdbonly @@ -51,38 +77,49 @@ prompt 4 AllRules.ruleset + + + false - - ..\..\..\lib\Mono.Data.Sqlite.dll + + ..\..\packages\ServiceStack.OrmLite.Sqlite.Mono.4.5.0\lib\net45\Mono.Data.Sqlite.dll + True - - ..\..\..\lib\ServiceStack.dll + + ..\..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True - - ..\..\..\lib\ServiceStack.Common.dll + + ..\..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True - - ..\..\..\lib\ServiceStack.Interfaces.dll + + ..\..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True - - ..\..\..\lib\ServiceStack.OrmLite.dll + + ..\..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True - - ..\..\..\lib\ServiceStack.OrmLite.Sqlite.dll + + ..\..\packages\ServiceStack.OrmLite.4.5.0\lib\net45\ServiceStack.OrmLite.dll + True - - ..\..\..\lib\ServiceStack.ServiceInterface.dll + + ..\..\packages\ServiceStack.OrmLite.Sqlite.Mono.4.5.0\lib\net45\ServiceStack.OrmLite.Sqlite.dll + True + + + ..\..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True - 3.5 - 3.5 - 3.5 @@ -94,6 +131,7 @@ + @@ -126,8 +164,7 @@ - - sqlite3.dll + PreserveNewest diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/packages.config b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/packages.config new file mode 100644 index 00000000..877f9ce2 --- /dev/null +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/sqlite3.dll b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/sqlite3.dll new file mode 100644 index 00000000..1058a2b1 Binary files /dev/null and b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Console/sqlite3.dll differ diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/AppHost.cs b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/AppHost.cs index 80234716..4b8323bf 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/AppHost.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/AppHost.cs @@ -1,71 +1,56 @@ -using System; -using Funq; -using ServiceStack.CacheAccess; -using ServiceStack.CacheAccess.Providers; -using ServiceStack.Common.Utils; -using ServiceStack.Configuration; -using ServiceStack.DataAccess; -using ServiceStack.Examples.ServiceInterface; -using ServiceStack.Examples.ServiceInterface.Support; -using ServiceStack.Logging; -using ServiceStack.Logging.Support.Logging; -using ServiceStack.OrmLite; -using ServiceStack.OrmLite.Sqlite; -using ServiceStack.Redis; -using ServiceStack.WebHost.Endpoints; - -namespace ServiceStack.Examples.Host.Web -{ - /// - /// An example of a AppHost to have your services running inside a webserver. - /// - public class AppHost - : AppHostBase - { - private static ILog log; - - public AppHost() - : base("ServiceStack Examples", typeof(GetFactorialService).Assembly) - { - LogManager.LogFactory = new ConsoleLogFactory(); - log = LogManager.GetLogger(typeof (AppHost)); - } - - public override void Configure(Container container) - { - //Permit modern browsers (e.g. Firefox) to allow sending of any REST HTTP Method - base.SetConfig(new EndpointHostConfig - { - GlobalResponseHeaders = - { - { "Access-Control-Allow-Origin", "*" }, - { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }, - }, - }); - - container.Register(new ConfigurationResourceManager()); - - container.Register(c => new ExampleConfig(c.Resolve())); - var appConfig = container.Resolve(); - - container.Register(c => - new OrmLiteConnectionFactory( - appConfig.ConnectionString.MapHostAbsolutePath(), - SqliteOrmLiteDialectProvider.Instance)); - - ConfigureDatabase.Init(container.Resolve()); - - - //register different cache implementations depending on availability - const bool hasRedis = false; - if (hasRedis) - container.Register(c => new BasicRedisClientManager()); - else - container.Register(c => new MemoryCacheClient()); - - - log.InfoFormat("AppHost Configured: " + DateTime.Now); - } - } - +using System; +using Funq; +using ServiceStack.Configuration; +using ServiceStack.Data; +using ServiceStack.Examples.ServiceInterface; +using ServiceStack.Examples.ServiceInterface.Support; +using ServiceStack.Formats; +using ServiceStack.Logging; +using ServiceStack.OrmLite; +using ServiceStack.OrmLite.Sqlite; + +namespace ServiceStack.Examples.Host.Web +{ + /// + /// An example of a AppHost to have your services running inside a web server. + /// + public class AppHost : AppHostBase + { + private static ILog log; + + public AppHost() : base("ServiceStack Examples", typeof(GetFactorialService).Assembly) + { + LogManager.LogFactory = new ConsoleLogFactory(); + log = LogManager.GetLogger(typeof (AppHost)); + } + + public override void Configure(Container container) + { + //Permit modern browsers (e.g. Firefox) to allow sending of any REST HTTP Method + base.SetConfig(new HostConfig + { + DebugMode = true, + }); + + Plugins.Add(new CorsFeature()); + + container.Register(new AppSettings()); + container.Register(c => new ExampleConfig(c.Resolve())); + + var appConfig = container.Resolve(); + + container.Register(c => + new OrmLiteConnectionFactory( + appConfig.ConnectionString.MapHostAbsolutePath(), + SqliteOrmLiteDialectProvider.Instance)); + + ConfigureDatabase.Init(container.Resolve()); + + //If you give Redis a try, you won't be disappointed. This however requires Redis to be installed. + //container.Register(c => new BasicRedisClientManager()); + + log.InfoFormat("AppHost Configured: {0}", DateTime.Now); + } + } + } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Global.asax.cs b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Global.asax.cs index fcae3b2c..333e2a1d 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Global.asax.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Global.asax.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Security; -using System.Web.SessionState; -using ServiceStack.Examples.ServiceInterface; +using System.Configuration; +using System.IO; +using ServiceStack.Configuration; namespace ServiceStack.Examples.Host.Web { @@ -13,6 +10,11 @@ public class Global : System.Web.HttpApplication protected void Application_Start(object sender, EventArgs e) { + if (File.Exists(@"C:\src\appsettings.license.txt")) + Licensing.RegisterLicenseFromFile(@"C:\src\appsettings.license.txt"); + else if (string.IsNullOrEmpty(ConfigUtils.GetNullableAppSetting("servicestack:license"))) + throw new ConfigurationErrorsException("A valid license key is required for this demo"); + var appHost = new AppHost(); appHost.Init(); } diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Properties/AssemblyInfo.cs b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Properties/AssemblyInfo.cs index 6148c365..731103bf 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Properties/AssemblyInfo.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Properties/AssemblyInfo.cs @@ -1,35 +1,35 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ServiceStack.Examples.Host.Web")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("ServiceStack.Examples.Host.Web")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ServiceStack.Examples.Host.Web")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("ServiceStack.Examples.Host.Web")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.1.1205.1040")] +[assembly: AssemblyFileVersion("1.1.1205.1040")] diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/ServiceStack.Examples.Host.Web.csproj b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/ServiceStack.Examples.Host.Web.csproj index cd5a7375..66306f29 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/ServiceStack.Examples.Host.Web.csproj +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/ServiceStack.Examples.Host.Web.csproj @@ -1,149 +1,173 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {3A8D2349-6E97-47A2-AC49-EFE7D89C0344} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - ServiceStack.Examples.Host.Web - ServiceStack.Examples.Host.Web - v3.5 - - - 3.5 - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - x86 - AllRules.ruleset - - - pdbonly - true - bin\ - TRACE - prompt - 4 - AllRules.ruleset - x86 - - - - ..\..\..\lib\Mono.Data.Sqlite.dll - - - False - ..\..\..\lib\ServiceStack.dll - - - ..\..\..\lib\ServiceStack.Common.dll - - - ..\..\..\lib\ServiceStack.Interfaces.dll - - - ..\..\..\lib\ServiceStack.OrmLite.dll - - - ..\..\..\lib\ServiceStack.OrmLite.Sqlite.dll - - - ..\..\..\lib\ServiceStack.Redis.dll - - - ..\..\..\lib\ServiceStack.ServiceInterface.dll - - - - - 3.5 - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - - sqlite3.dll - PreserveNewest - - - - - Designer - - - - - - ASPXCodeBehind - Default.aspx - - - Default.aspx - - - Global.asax - - - - - - {519A7B72-D144-436D-AAC3-7BAAEAD3FF52} - ServiceStack.Examples.ServiceInterface - - - - - - - - - - - - - True - True - 59436 - / - http://localhost/ServiceStack.Examples.Host.Web - False - False - - - False - - - - + + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {3A8D2349-6E97-47A2-AC49-EFE7D89C0344} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + ServiceStack.Examples.Host.Web + ServiceStack.Examples.Host.Web + v4.5 + + + 4.0 + + + false + + + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + x86 + AllRules.ruleset + false + + + pdbonly + true + bin\ + TRACE + prompt + 4 + AllRules.ruleset + x86 + false + + + + ..\..\packages\ServiceStack.OrmLite.Sqlite.Mono.4.5.0\lib\net45\Mono.Data.Sqlite.dll + True + + + ..\..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True + + + ..\..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True + + + ..\..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True + + + ..\..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True + + + ..\..\packages\ServiceStack.OrmLite.4.5.0\lib\net45\ServiceStack.OrmLite.dll + True + + + ..\..\packages\ServiceStack.OrmLite.Sqlite.Mono.4.5.0\lib\net45\ServiceStack.OrmLite.Sqlite.dll + True + + + ..\..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + Designer + + + + + + ASPXCodeBehind + Default.aspx + + + Default.aspx + + + Global.asax + + + + + + {519A7B72-D144-436D-AAC3-7BAAEAD3FF52} + ServiceStack.Examples.ServiceInterface + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + + False + True + 64067 + / + http://localhost/ServiceStack.Examples.Host.Web + False + False + + + False + + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Web.config b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Web.config index 069fc4ba..26a15690 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Web.config +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/Web.config @@ -2,49 +2,49 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +
    + - - - - - - - - - - - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/clientaccesspolicy.xml b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/clientaccesspolicy.xml new file mode 100644 index 00000000..513ee371 --- /dev/null +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/clientaccesspolicy.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/crossdomain.xml b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/crossdomain.xml new file mode 100644 index 00000000..b716a00f --- /dev/null +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/crossdomain.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/packages.config b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/packages.config new file mode 100644 index 00000000..877f9ce2 --- /dev/null +++ b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/sqlite3.dll b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/sqlite3.dll new file mode 100644 index 00000000..1058a2b1 Binary files /dev/null and b/src/ServiceStack.Examples/ServiceStack.Examples.Host.Web/sqlite3.dll differ diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/DeleteAllUsersService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/DeleteAllUsersService.cs index 835eb1c3..3b78cd53 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/DeleteAllUsersService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/DeleteAllUsersService.cs @@ -1,31 +1,21 @@ -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Examples.ServiceModel.Types; using ServiceStack.OrmLite; -using ServiceStack.ServiceHost; namespace ServiceStack.Examples.ServiceInterface { - /// - /// The service or 'Port' handler that will be used to execute the request. - /// - /// The 'Port' attribute is used to link the 'service request' to the 'service implementation' - /// - public class DeleteAllUsersService - : IService - { - //Example of ServiceStack's IOC property injection - public IDbConnectionFactory ConnectionFactory { get; set; } - - public object Execute(DeleteAllUsers request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - dbCmd.DeleteAll(); - - return new DeleteAllUsersResponse(); - } - } - } + /// + /// The service or 'Port' handler that will be used to execute the request. + /// + /// The 'Port' attribute is used to link the 'service request' to the 'service implementation' + /// + public class DeleteAllUsersService : Service + { + public object Any(DeleteAllUsers request) + { + Db.DeleteAll(); + return new DeleteAllUsersResponse(); + } + } } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ExampleConfig.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ExampleConfig.cs index 049adb89..0dae107c 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ExampleConfig.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ExampleConfig.cs @@ -1,4 +1,3 @@ -using ServiceStack.Common.Utils; using ServiceStack.Configuration; namespace ServiceStack.Examples.ServiceInterface @@ -12,7 +11,7 @@ public class ExampleConfig public ExampleConfig() { } - public ExampleConfig(IResourceManager appConfig) + public ExampleConfig(IAppSettings appConfig) { ConnectionString = appConfig.GetString("ConnectionString"); DefaultFibonacciLimit = appConfig.Get("DefaultFibonacciLimit", 10); diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetAllUsersService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetAllUsersService.cs index 10188d94..66ba2211 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetAllUsersService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetAllUsersService.cs @@ -1,25 +1,16 @@ -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Examples.ServiceModel.Types; using ServiceStack.OrmLite; -using ServiceStack.ServiceHost; namespace ServiceStack.Examples.ServiceInterface { - public class GetAllUsersService - : IService - { - //Example of ServiceStack's IOC property injection - public IDbConnectionFactory ConnectionFactory { get; set; } - - public object Execute(GetAllUsers request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - var users = dbCmd.Select(); - return new GetAllUsersResponse { Users = new ArrayOfUser(users) }; - } - } - } + public class GetAllUsersService : Service + { + public object Any(GetAllUsers request) + { + var users = Db.Select(); + return new GetAllUsersResponse { Users = new ArrayOfUser(users) }; + } + } } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFactorialService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFactorialService.cs index 6b6070e4..e8172d09 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFactorialService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFactorialService.cs @@ -1,5 +1,4 @@ -using ServiceStack.Examples.ServiceModel.Operations; -using ServiceStack.ServiceHost; +using ServiceStack.Examples.ServiceModel; namespace ServiceStack.Examples.ServiceInterface { @@ -7,10 +6,9 @@ namespace ServiceStack.Examples.ServiceInterface /// The purpose of this example is to show the minimum number and detail of classes /// required in order to implement a simple service. /// - public class GetFactorialService - : IService + public class GetFactorialService : Service { - public object Execute(GetFactorial request) + public GetFactorialResponse Any(GetFactorial request) { return new GetFactorialResponse { Result = GetFactorial(request.ForNumber) }; } diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFibonacciNumbersService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFibonacciNumbersService.cs index 4cbd4b0c..f22415b9 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFibonacciNumbersService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetFibonacciNumbersService.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using ServiceStack.Examples.ServiceModel.Operations; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface.ServiceModel; +using ServiceStack.Examples.ServiceModel; namespace ServiceStack.Examples.ServiceInterface { @@ -11,8 +9,7 @@ namespace ServiceStack.Examples.ServiceInterface /// This purpose of this example is how you would implement a slightly more advanced /// web service returning a slightly more 'complex object'. /// - public class GetFibonacciNumbersService - : IService + public class GetFibonacciNumbersService : Service { private readonly ExampleConfig config; @@ -22,7 +19,7 @@ public GetFibonacciNumbersService(ExampleConfig config) this.config = config; } - public object Execute(GetFibonacciNumbers request) + public GetFibonacciNumbersResponse Any(GetFibonacciNumbers request) { var skip = request.Skip.GetValueOrDefault(0); var take = request.Take.GetValueOrDefault(config.DefaultFibonacciLimit); diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersCachedService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersCachedService.cs index 349f0402..171747a4 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersCachedService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersCachedService.cs @@ -1,9 +1,5 @@ using System; -using ServiceStack.CacheAccess; -using ServiceStack.Common.Utils; -using ServiceStack.Examples.ServiceModel.Operations; -using ServiceStack.ServiceHost; -using ServiceStack.WebHost.Endpoints; +using ServiceStack.Examples.ServiceModel; namespace ServiceStack.Examples.ServiceInterface { @@ -11,19 +7,8 @@ namespace ServiceStack.Examples.ServiceInterface /// This is an example showing how you can take advantage of ServiceStack's built-in /// support for caching in your webservices. /// - public class GetNorthwindCustomerOrdersCachedService - : IService - - //Tell ServiceStack that this service requires access to the request context - , IRequiresRequestContext + public class GetNorthwindCustomerOrdersCachedService : Service { - //ServiceStack injects the RequestContext in this property - public IRequestContext RequestContext { get; set; } - - //ServiceStack IOC injects the registered ICacheClient provider (if any) in this property - public ICacheClient CacheClient { get; set; } - - public object Execute(GetNorthwindCustomerOrdersCached request) { //create a unique urn to cache these results against @@ -31,7 +16,7 @@ public object Execute(GetNorthwindCustomerOrdersCached request) //Removes all the cached results at this cacheKey if (request.RefreshCache) - RequestContext.RemoveFromCache(this.CacheClient, cacheKey); + Request.RemoveFromCache(this.Cache, cacheKey); /*Return the most optimized result path based upon the incoming request context: + If a cache of the result for the content-type already exists, then: @@ -43,15 +28,11 @@ public object Execute(GetNorthwindCustomerOrdersCached request) - the serailized contentType stored at e.g: Cache[urn:custorders:1.xml] = result.xml - the compressed serialized result stored at e.g: Cache[urn:custorders:1.xml.deflate] = result.xml.deflate */ - return RequestContext.ToOptimizedResultUsingCache(this.CacheClient, cacheKey, () => - new GetNorthwindCustomerOrdersCachedResponse - { + return Request.ToOptimizedResultUsingCache(this.Cache, cacheKey, () => + new GetNorthwindCustomerOrdersCachedResponse { CreatedDate = DateTime.UtcNow, //To determine when this cached result was created CustomerOrders = GetNorthwindCustomerOrdersService.GetCustomerOrders(request.CustomerId) }); } - } - - } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersService.cs index 3a1f16bf..2e2e54f7 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetNorthwindCustomerOrdersService.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Examples.ServiceModel.Types; -using ServiceStack.ServiceHost; namespace ServiceStack.Examples.ServiceInterface { @@ -10,10 +9,9 @@ namespace ServiceStack.Examples.ServiceInterface /// This is an example of a detailed web service to illustrate how its defined /// ServiceStack and to see what it looks like on the different endpoints. /// - public class GetNorthwindCustomerOrdersService - : IService + public class GetNorthwindCustomerOrdersService : Service { - public object Execute(GetNorthwindCustomerOrders request) + public object Any(GetNorthwindCustomerOrders request) { return new GetNorthwindCustomerOrdersResponse { diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetUsersService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetUsersService.cs index 072b751b..02a96d71 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetUsersService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GetUsersService.cs @@ -1,42 +1,33 @@ using System.Collections.Generic; -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Examples.ServiceModel.Types; using ServiceStack.OrmLite; -using ServiceStack.ServiceHost; namespace ServiceStack.Examples.ServiceInterface { - /// - /// The service handler that will be used to execute the request. - /// - /// This example shows a simple introduction into SOA-like webservices. - /// i.e. group similar operations into a single 'document-centric like' service request. - /// - public class GetUsersService : IService - { - //Example of ServiceStack's built-in Funq IOC property injection - public IDbConnectionFactory ConnectionFactory { get; set; } + /// + /// The service handler that will be used to execute the request. + /// + /// This example shows a simple introduction into SOA-like webservices. + /// i.e. group similar operations into a single 'document-centric like' service request. + /// + public class GetUsersService : Service + { + public GetUsersResponse Any(GetUsers request) + { + var users = new List(); - public object Execute(GetUsers request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - var users = new List(); + if (request.UserIds != null && request.UserIds.Count > 0) + { + users.AddRange(Db.SelectByIds(request.UserIds)); + } - if (request.UserIds != null && request.UserIds.Count > 0) - { - users.AddRange(dbCmd.GetByIds(request.UserIds)); - } + if (request.UserNames != null && request.UserNames.Count > 0) + { + users.AddRange(Db.Select(q => request.UserNames.Contains(q.UserName))); + } - if (request.UserNames != null && request.UserNames.Count > 0) - { - users.AddRange(dbCmd.Select( - "UserName IN ({0})", request.UserNames.SqlInValues())); - } - - return new GetUsersResponse { Users = new ArrayOfUser(users) }; - } - } - } + return new GetUsersResponse { Users = new ArrayOfUser(users) }; + } + } } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GreetService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GreetService.cs index cd102aa9..64f611e5 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GreetService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/GreetService.cs @@ -1,14 +1,13 @@ -using ServiceStack.Examples.ServiceModel.Operations; -using ServiceStack.ServiceHost; +using ServiceStack.Examples.ServiceModel; namespace ServiceStack.Examples.ServiceInterface { /// /// An example of a very basic web service /// - public class GreetService : IService + public class GreetService : Service { - public object Execute(Greet request) + public object Any(Greet request) { return new GreetResponse { Result = "Hello " + request.Name }; } diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/MovieRestService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/MovieRestService.cs index 8556012e..9c8ee644 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/MovieRestService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/MovieRestService.cs @@ -1,120 +1,93 @@ -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Examples.ServiceModel.Types; using ServiceStack.Logging; using ServiceStack.OrmLite; -using ServiceStack.ServiceHost; namespace ServiceStack.Examples.ServiceInterface { - /// - /// An example of a basic REST web service - /// - /// Each operation needs to support same Request and Response DTO's so you will - /// need to combine the types of all your operations into the same DTO as done - /// in this example. - /// - public class MovieRestService - : IService - , IRestGetService - , IRestPutService - , IRestPostService - , IRestDeleteService - , IRequiresRequestContext //Ask ServiceStack to inject the RequestContext - { - private static readonly ILog Log = LogManager.GetLogger(typeof(MovieRestService)); + /// + /// An example of a basic REST web service + /// + /// Each operation needs to support same Request and Response DTO's so you will + /// need to combine the types of all your operations into the same DTO as done + /// in this example. + /// + public class MovieRestService : Service + { + private static readonly ILog Log = LogManager.GetLogger(typeof(MovieRestService)); - public IRequestContext RequestContext { get; set; } - - public IDbConnectionFactory ConnectionFactory { get; set; } + public object Any(Movies request) + { + return Get(request); + } - public object Execute(Movies request) - { - return Get(request); - } + /// + /// GET /Movies + /// GET /Movies?Id={Id} + /// + /// + /// + public object Get(Movies request) + { + //Alternatively you can infer the HTTP method by inspecting the RequestContext attributes + Log.InfoFormat("Using RequestContext to inspect Endpoint attributes: {0}", + this.Request.RequestAttributes); - /// - /// GET /Movies - /// GET /Movies?Id={Id} - /// - /// - /// - public object Get(Movies request) - { - //Alternatively you can infer the HTTP method by inspecting the RequestContext attributes - Log.InfoFormat("Using RequestContext to inspect Endpoint attributes: {0}", - this.RequestContext.EndpointAttributes); + var response = new MoviesResponse(); - var response = new MoviesResponse(); + if (request.Id != null) + { + // GET /Movies?Id={request.Id} + var movie = Db.SingleById(request.Id); + if (movie != null) + { + response.Movies.Add(movie); + } + } + else + { + // GET /Movies + response.Movies = Db.Select(); + } - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - if (request.Id != null) - { - // GET /Movies?Id={request.Id} - var movie = dbCmd.GetByIdOrDefault(request.Id); - if (movie != null) - { - response.Movies.Add(movie); - } - } - else - { - // GET /Movies - response.Movies = dbCmd.Select(); - } - } + return response; + } - return response; - } + /// + /// PUT /Movies + /// + /// + /// + public object Put(Movies request) + { + Db.Insert(request.Movie); - /// - /// PUT /Movies - /// - /// - /// - public object Put(Movies request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - dbCmd.Insert(request.Movie); - } + return new MoviesResponse(); + } - return new MoviesResponse(); - } + /// + /// DELETE /Movies + /// + /// + /// + public object Delete(Movies request) + { + Db.DeleteById(request.Id); - /// - /// DELETE /Movies - /// - /// - /// - public object Delete(Movies request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - dbCmd.DeleteById(request.Id); - } + return new MoviesResponse(); + } - return new MoviesResponse(); - } + /// + /// POST /Movies + /// + /// + /// + public object Post(Movies request) + { + Db.Update(request.Movie); - /// - /// POST /Movies - /// - /// - /// - public object Post(Movies request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - dbCmd.Update(request.Movie); - } - - return new MoviesResponse(); - } - } + return new MoviesResponse(); + } + } } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/Properties/AssemblyInfo.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/Properties/AssemblyInfo.cs index 70b71c95..2767de6f 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/Properties/AssemblyInfo.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/Properties/AssemblyInfo.cs @@ -1,43 +1,43 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ServiceStack.Examples.ServiceInterface")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("ServiceStack.Examples.ServiceInterface")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("ce46bc2e-a265-4aea-9345-6745b66baeeb")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] - -/* Setting the default DataContract namespace using the attributes below is not supported in Mono */ -[assembly: ContractNamespace("http://schemas.servicestack.net/types", - ClrNamespace = "ServiceStack.Examples.ServiceInterface")] -[assembly: ContractNamespace("http://schemas.servicestack.net/types", - ClrNamespace = "ServiceStack.Examples.ServiceInterface.Types")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ServiceStack.Examples.ServiceInterface")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("ServiceStack.Examples.ServiceInterface")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ce46bc2e-a265-4aea-9345-6745b66baeeb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.1205.1040")] +[assembly: AssemblyFileVersion("1.1.1205.1040")] + +/* Setting the default DataContract namespace using the attributes below is not supported in Mono */ +[assembly: ContractNamespace("http://schemas.servicestack.net/types", + ClrNamespace = "ServiceStack.Examples.ServiceInterface")] +[assembly: ContractNamespace("http://schemas.servicestack.net/types", + ClrNamespace = "ServiceStack.Examples.ServiceInterface.Types")] diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ResetMovieDatabaseService.cs b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ResetMovieDatabaseService.cs index 2404d81c..e808a595 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ResetMovieDatabaseService.cs +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ResetMovieDatabaseService.cs @@ -1,28 +1,24 @@ +using ServiceStack.Data; using ServiceStack.Examples.ServiceInterface.Support; -using ServiceStack.Examples.ServiceModel.Operations; +using ServiceStack.Examples.ServiceModel; using ServiceStack.Examples.ServiceModel.Types; using ServiceStack.OrmLite; -using ServiceStack.ServiceHost; namespace ServiceStack.Examples.ServiceInterface { - /// - /// An example of a very basic web service - /// - public class ResetMovieDatabaseService : IService - { - public IDbConnectionFactory ConnectionFactory { get; set; } + /// + /// An example of a very basic web service + /// + public class ResetMovieDatabaseService : Service + { + public IDbConnectionFactory ConnectionFactory { get; set; } - public object Execute(ResetMovieDatabase request) - { - using (var dbConn = ConnectionFactory.OpenDbConnection()) - using (var dbCmd = dbConn.CreateCommand()) - { - dbCmd.CreateTable(true); - dbCmd.SaveAll(ConfigureDatabase.Top5Movies); - } + public object Any(ResetMovieDatabase request) + { + Db.CreateTable(true); + Db.SaveAll(ConfigureDatabase.Top5Movies); - return new ResetMovieDatabaseResponse(); - } - } + return new ResetMovieDatabaseResponse(); + } + } } \ No newline at end of file diff --git a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ServiceStack.Examples.ServiceInterface.csproj b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ServiceStack.Examples.ServiceInterface.csproj index a70b768a..49d7fdb4 100644 --- a/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ServiceStack.Examples.ServiceInterface.csproj +++ b/src/ServiceStack.Examples/ServiceStack.Examples.ServiceInterface/ServiceStack.Examples.ServiceInterface.csproj @@ -10,7 +10,7 @@ Properties ServiceStack.Examples.ServiceInterface ServiceStack.Examples.ServiceInterface - v3.5 + v4.5 512 @@ -31,6 +31,7 @@ false false true + true @@ -41,6 +42,7 @@ prompt 4 AllRules.ruleset + false pdbonly @@ -50,38 +52,41 @@ prompt 4 AllRules.ruleset + false - - ..\..\..\lib\ServiceStack.dll + + ..\..\packages\ServiceStack.4.5.0\lib\net45\ServiceStack.dll + True - - ..\..\..\lib\ServiceStack.Common.dll + + ..\..\packages\ServiceStack.Client.4.5.0\lib\net45\ServiceStack.Client.dll + True - - ..\..\..\lib\ServiceStack.Interfaces.dll + + ..\..\packages\ServiceStack.Common.4.5.0\lib\net45\ServiceStack.Common.dll + True - - ..\..\..\lib\ServiceStack.OrmLite.dll + + ..\..\packages\ServiceStack.Interfaces.4.5.0\lib\portable-wp80+sl5+net45+win8+wpa81+monotouch+monoandroid+xamarin.ios10\ServiceStack.Interfaces.dll + True - - ..\..\..\lib\ServiceStack.ServiceInterface.dll + + ..\..\packages\ServiceStack.OrmLite.4.5.0\lib\net45\ServiceStack.OrmLite.dll + True - - ..\..\..\lib\ServiceStack.Text.dll + + ..\..\packages\ServiceStack.Text.4.5.0\lib\net45\ServiceStack.Text.dll + True - 3.5 - 3.0 - 3.5 - 3.5 @@ -126,6 +131,9 @@ true + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + The following attributes can be set on the tag. + + + + --> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.Hello/default.htm b/src/ServiceStack.Hello/default.htm index 2f4d1b18..ae0d8649 100644 --- a/src/ServiceStack.Hello/default.htm +++ b/src/ServiceStack.Hello/default.htm @@ -1,391 +1,320 @@ - - + Tutorial - Creating a Hello World ServiceStack Web Service - - + - - ServiceStack Home - + + ServiceStack Home - - - -

    Creating a Web service from scratch with Service Stack

    - + + +

    + Creating a Web service from scratch with Service Stack

    This tutorial will go through and develop and call a simple Hello world Web Service - from scratch using Service Stack and VS.NET. + from scratch using Service Stack and VS.NET.

    - - -

    1. Creating your application

    + +

    + Installing via NuGet

    - Create a new ASP.NET Web Application by going into Visual Studio - and selecting File -> New -> Project on the File menu. + If you have NuGet you can skip steps 1 - 3 below by installing one of the NuGet + Host packages below:

    -

    New ASP.NET Project

    - -

    2. Configuring Service Stack to run in your application

    +

    + Install ServiceStack Only at root path + / +

    - Add a reference to the latest ServiceStack.dll's to your project: + Create an empty ASP.NET Web Application and

    - - +
    +

    +

    PM> Install-Package ServiceStack.Host.AspNet
    +

    +
    +

    + Install ServiceStack Side-by-Side with ASP.NET MVC at custom path /api +

    - There are 2 supported options available to register ServiceStack in your ASP.NET application Web.config: + Create an empty ASP.NET MVC Web Application and +

    +
    +

    +

    PM> Install-Package ServiceStack.Host.Mvc
    +

    +
    +

    + Completing the NuGet Installation

    +

    + The NuGet package provides an AppHost template in your project at App_Start\AppHost.cs + and some App_Start\WebServiceExamples.cs to get you started.

    - -

    a) You do not require an existing Web Framework - Host from the root path: /

    -

    - You can host at the root path / when you don't need to use an existing Web Framework with your ServiceStack web services (i.e. project only has static files) -

    -

    The configuration below allows you to host your webservices from the root path: /

    -<system.web> - <httpHandlers> - <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/> - </httpHandlers> -</system.web> - -<!-- Required for IIS 7.0 --> -<system.webServer> - <handlers> - <add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" /> - </handlers> -</system.webServer> - - -

    b) You want to use ServiceStack with an existing Web Framework - Host web services at: /custompath

    -

    - In order to avoid conflicts with your existing ASP.NET web framework it is recommended to host your ServiceStack web services at a custom path.
    - This will allow you to use ServiceStack together with an existing web framework - e.g. ASP.NET MVC 3 or FUBU MVC, etc. -

    -

    The location configuration below hosts your webservices at custom path: /servicestack

    -<location path="servicestack"> - <system.web> - <httpHandlers> - <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/> - </httpHandlers> - </system.web> - - <!-- Required for IIS 7.0 --> - <system.webServer> - <modules runAllManagedModulesForAllRequests="true"/> - <validation validateIntegratedModeConfiguration="false" /> - <handlers> - <add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" /> - </handlers> - </system.webServer> -</location> - -<!-- Required for MONO --> -<system.web> - <httpHandlers> - <add path="servicestack*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/> - </httpHandlers> -</system.web> -<system.webServer> - <validation validateIntegratedModeConfiguration="false" /> -</system.webServer> - -

    - Note: due to limitations in IIS 6 - the /custompath must end with .ashx, e.g: path="servicestack.ashx" -

    - -

    3. Creating your first Web Service

    -

    - For simplicity we will add the Web Service and the start up script all in the same Global.asax.cs. - To do this Right-click on your project and go
    + After looking at the README.txt - Skip the Manual Installation instructions + below and start exploring ServiceStack features at: +

    +

    +

    + Viewing your Web Service >>

    +

    + +

    + Install Manually - 1. Creating your application

    +

    + Create a new ASP.NET Web Application by going into Visual Studio and selecting + File -> New -> Project on the File menu. +

    +

    + New ASP.NET Project

    +

    + 2. Configuring Service Stack to run in your application

    +

    + Add a reference to the ServiceStack dlls with: +

    +
    +

    +

    PM> Install-Package ServiceStack
    +

    +
    +

    + There are 2 supported options available to register ServiceStack in your ASP.NET + application Web.config: +

    +

    + a) You do not require an existing Web Framework - Host from + the root path: /

    +

    + You can host at the root path / when you don't need to use an existing Web + Framework with your ServiceStack web services (i.e. project only has static files) +

    +

    + The configuration below allows you to host your webservices from the root path: + /

    + +    <system.web> +      <httpHandlers> +        <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*"/> +      </httpHandlers> +    </system.web> + +    <!-- Required for IIS7 --> +    <system.webServer> +      <modules runAllManagedModulesForAllRequests="true"/> +      <validation validateIntegratedModeConfiguration="false" /> +      <handlers> +        <add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" /> +      </handlers> +    </system.webServer> + +

    + b) You want to use ServiceStack with an existing Web Framework + - Host web services at: /custompath

    +

    + In order to avoid conflicts with your existing ASP.NET web framework it is recommended + to host your ServiceStack web services at a custom path.
    + This will allow you to use ServiceStack together with an existing web framework + e.g. ASP.NET MVC 3 or + FUBU MVC, etc. +

    +

    + The location configuration below hosts your webservices at custom path: /api

    + +  <!-- ServiceStack: Required to host at: /servicestack --> +  <location path="api"> +    <system.web> +      <httpHandlers> +        <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*"/> +      </httpHandlers> +    </system.web> + +    <!-- Required for IIS7 --> +    <system.webServer> +      <modules runAllManagedModulesForAllRequests="true"/> +      <validation validateIntegratedModeConfiguration="false" /> +      <handlers> +        <add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" /> +      </handlers> +    </system.webServer> +  </location> +  <!-- Required for MONO --> +  <system.web> +    <httpHandlers> +      <add path="api*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*"/> +    </httpHandlers> +  </system.web> +  <!-- Required for IIS7 --> +  <system.webServer> +    <!-- ServiceStack: Required --> +    <validation validateIntegratedModeConfiguration="false"/> +  </system.webServer> + +

    + Note: Due to limitations in IIS 6 - the /custompath must end with .ashx, + e.g: path="api.ashx" +

    +

    + To avoid conflicts with ASP.NET MVC add ignore rule in Global.asax RegisterRoutes + method e.g: routes.IgnoreRoute ("api/{*pathInfo}"); +

    + +

    + 3. Creating your first Web Service

    +

    + For simplicity we will add the Web Service and the start up script all in the same + Global.asax.cs. To do this Right-click on your project and go +
    Add -> New Item then select the Global Application class.

    Within the same file add the following code:

    - -

    1. Create the name of your Web Service (i.e. the Request DTO)

    -public class Hello -{ - public string Name { get; set; } -} - - -

    2. Define what your Web Service will return (i.e. Response DTO)

    -public class HelloResponse -{ - public string Result { get; set; } -} - - -

    3. Create your Web Service implementation

    -public class HelloService : IService<Hello> -{ - public object Execute(Hello request) - { - return new HelloResponse { Result = "Hello, " + request.Name }; - } -} - - - -

    Registering your web services and starting your application

    - - The final step is to Configure setup to tell Service Stack where to find your web services: - - -

    Web Service AppHost Singleton

    -public class Global : System.Web.HttpApplication -{ - public class HelloAppHost : AppHostBase - { - //Tell Service Stack the name of your application and where to find your web services - public HelloAppHost() : base("Hello Web Services", typeof(HelloService).Assembly) { } - - public override void Configure(Container container) - { - //register user-defined REST-ful urls - Routes - .Add<Hello>("/hello") - .Add<Hello>("/hello/{Name}"); - } - } - - //Initialize your application singleton - protected void Application_Start(object sender, EventArgs e) - { - new HelloAppHost().Init(); - } -} - - +

    + 1. Create the name of your Web Service (i.e. the Request DTO)

    +     /// <summary> +    /// Define your ServiceStack web service request (i.e. the Request DTO). +    /// </summary>     +    public class Hello +    { +        public string Name { getset; } +    } +

    + 2. Define what your Web Service will return (i.e. Response DTO)

    +     /// <summary> +    /// Define your ServiceStack web service response (i.e. Response DTO). +    /// </summary> +    public class HelloResponse +    { +        public string Result { getset; } +    } + +

    + 3. Create your Web Service implementation

    +     /// <summary> +    /// Create your ServiceStack web service implementation. +    /// </summary> +    public class HelloService : IService +    { +        public object Any(Hello request) +        { +            //Looks strange when the name is null so we replace with a generic name. +            var name = request.Name ?? "John Doe"; +            return new HelloResponse { Result = "Hello, " + name }; +        } +    } + +

    + Registering your web services and starting your application

    + The final step is to Configure setup to tell Service Stack where to find your web + services: +

    + Web Service AppHost Singleton

    +     public class Global : System.Web.HttpApplication +    { +        /// <summary> +        /// Create your ServiceStack web service application with a singleton AppHost. +        /// </summary>         +        public class HelloAppHost : AppHostBase +        { +            /// <summary> +            /// Initializes a new instance of your ServiceStack application, with the specified name and assembly containing the services. +            /// </summary> +            public HelloAppHost() : base("Hello Web Services"typeof(HelloService).Assembly) { } + +            /// <summary> +            /// Configure the container with the necessary routes for your ServiceStack application. +            /// </summary> +            /// <param name="container">The built-in IoC used with ServiceStack.</param> +            public override void Configure(Container container) +            { +                //Register user-defined REST-ful urls. You can access the service at the url similar to the following. +                //http://localhost/ServiceStack.Hello/servicestack/hello or http://localhost/ServiceStack.Hello/servicestack/hello/John%20Doe +                //You can change /servicestack/ to a custom path in the web.config. +                Routes +                  .Add<Hello>("/hello") +                  .Add<Hello>("/hello/{Name}"); +            } +        } + +        protected void Application_Start(object sender, EventArgs e) +        { +            //Initialize your application +            (new HelloAppHost()).Init(); +        } +    } +

    Done! You now have a working application :)

    - - -

    Viewing your Web Services

    + +

    + Viewing your Web Services

    - Now that you have a working Web Service lets see what ServiceStack does for you out of the box: + Now that you have a working Web Service lets see what ServiceStack does for you + out of the box:

    - -

    The Web Service Index Metadata page

    +

    + The Web Service Index Metadata page

    - If everything is configured correctly you can go to the - /servicestack/metadata - to see a list of your web services and the various end points its available on. + If everything is configured correctly you can go to the + /api/metadata to see a list of your web services and the + various end points its available on.

    - -

    Service Stack Metadata page

    - +

    + Service Stack Metadata page

    The Metadata page contains:

      -
    • - A list of all your webservices and the endpoints they are available on. -
    • -
    • - A list of coding examples showing you how to call each endpoing a number of different ways. -
    • -
    • - Links to all the XSD types used by your web services -
    • -
    • - Links to the web services SOAP 1.1 / 1.2 WSDLs -
    • +
    • A list of all your webservices and the endpoints they are available on.
    • +
    • A list of coding examples showing you how to call each endpoint a number of different + ways.
    • +
    • Links to all the XSD types used by your web services
    • +
    • Links to the web services SOAP 1.1 / 1.2 WSDLs

    - -

    The different ways of calling your Web Service

    - +

    + The different ways of calling your Web Service

    - Without any configuration required, your web services are callable - via the following endpoints, formats and calling convetions. + Without any configuration required, your web services are callable via the following + endpoints, formats and calling conventions.

    -
    - -

    XML (POX), JSON, JSV, CSV urls

    -

    - /servicestack/[xml|json|html|jsv|csv]/[syncreply|asynconeway]/[servicename] -

    - -

    SOAP Web Service urls

    -

    - /servicestack/[soap11|soap12] -

    - -

    User defined REST-ful urls

    -

    - Accessible via any REST-ful urls defined using the [RestService] Attribute. e.g. in this case: -

    -

    - /servicestack/hello/{Name} -

    - +

    + XML (POX), JSON, JSV, CSV urls

    +

    + /api/[xml|json|html|jsv|csv]/[reply|oneway]/[servicename] +

    +

    + SOAP Web Service urls

    +

    + /api/[soap11|soap12] +

    +

    + User defined REST-ful urls

    +

    + Accessible via any REST-ful urls defined using the [RestService] Attribute. e.g. + in this case: +

    +

    + /api/hello/{Name} +

    - - -

    XML, JSON, - HTML5, - JSV, - CSV - Web Services via HTTP GET or POST

    + +

    + XML, JSON, + HTML5, + JSV, + CSV Web Services via HTTP GET or POST

    @@ -409,16 +338,17 @@

    XML, JSON, XML

    @@ -427,16 +357,17 @@

    XML, JSON, JSON

    @@ -445,16 +376,17 @@

    XML, JSON, HTML

    @@ -463,16 +395,17 @@

    XML, JSON, JSV

    @@ -481,166 +414,211 @@

    XML, JSON, CSV

    - /servicestack/xml/syncreply/Hello?Name=World + /api/xml/reply/Hello?Name=World - /servicestack/xml/syncreply/Hello + /api/xml/reply/Hello
    - - - + + +
    - /servicestack/json/syncreply/Hello?Name=World + /api/json/reply/Hello?Name=World - /servicestack/json/syncreply/Hello + /api/json/reply/Hello
    - - - + + +
    - /servicestack/html/syncreply/Hello?Name=World + /api/html/reply/Hello?Name=World - /servicestack/html/syncreply/Hello + /api/html/reply/Hello
    - - - + + +
    - /servicestack/jsv/syncreply/Hello?Name=World + /api/jsv/reply/Hello?Name=World - /servicestack/jsv/syncreply/Hello + /api/jsv/reply/Hello
    - - - + + +
    - /servicestack/csv/syncreply/Hello?Name=World + /api/csv/reply/Hello?Name=World - /servicestack/csv/syncreply/Hello + /api/csv/reply/Hello
    - - - + + +
    - -

    CONTENT TYPE

    +

    + CONTENT TYPE

    The endpoint type and resulting serialization format of your web service.

    - -

    HTTP GET

    +

    + HTTP GET

    - The url to call your web service using only the url and the query string to populate the request.
    + The url to call your web service using only the url and the query string to populate + the request.

    - - NOTE: Service Stack also lets you submit any arbitary complex type - (using JSV format) - via the query string or form data: - see this example. - + NOTE: Service Stack also lets you submit any arbitary complex type (using JSV format) + via the query string or form data: + see this example.

    - -

    HTTP POST CONTENT TYPE

    +

    + HTTP POST CONTENT TYPE

    - You can HTTP POST the 'Content Type' representation of the Request DTO to the same url. - Check the links to the metadata page for examples of this. + You can HTTP POST the 'Content Type' representation of the Request DTO to the same + url. Check the links to the metadata page for examples of this.

    - -

    HTTP POST FORM DATA

    -

    - As an alternative to posting the Content Type, each service also accepts - x-www-form-urlencoded Content-Types allowing you to call each web service - using a HTML FORM. Here is the HTML for the live examples: -

    -<form action="servicestack/xml/syncreply/Hello" method="post"> - <label>Name:</label> - <input type="text" name="Name" value="World!"> - <input type="submit"> -</form> - - -

    SOAP Web Services

    - +

    + HTTP POST FORM DATA

    +

    + As an alternative to posting the Content Type, each service also accepts x-www-form-urlencoded + Content-Types allowing you to call each web service using a HTML FORM. Here is the + HTML for the live examples: +

    + <form action="api/xml/syncreply/Hello" method="post"> +   <label>Name:</label> +   <input type="text" name="Name" value="World!" /> +   <input type="submit" /> +</form> +

    + Example:
    +

    + + + +
    +

    +

    + SOAP Web Services

    - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + +
    SOAP VERSIONWSDL + END POINTSSOAP EXAMPLE
    SOAP 1.1/servicestack/soap11soap11/metadata?op=Hello
    SOAP 1.2/servicestack/soap12soap12/metadata?op=Hello
    + SOAP VERSION + + WSDL + END POINTS + + SOAP EXAMPLE +
    + SOAP 1.1 + + /api/soap11 + + soap11/metadata?op=Hello +
    + SOAP 1.2 + + /api/soap12 + + soap12/metadata?op=Hello +
    -

    WSDL + END POINTS

    +

    + WSDL + END POINTS

    - A HTTP GET on the url returns the WSDL, while HTTP POST-ing a SOAP Request calls the web service. + A HTTP GET on the url returns the WSDL, while HTTP POST-ing + a SOAP Request calls the web service.

    -

    SOAP EXAMPLE

    +

    + SOAP EXAMPLE

    Shows example of what a SOAP Request looks like.

    - - -

    REST Web Services

    + +

    + REST Web Services

    - A new addition to Service Stack is the ability to define your own custom urls letting you - expose your web services via REST-ful urls. + A new addition to Service Stack is the ability to define your own custom urls letting + you expose your web services via REST-ful urls.

    Defining user-defined REST-ful urls can be done in one of two ways:

      -
    • Using the MVC-like Routes config property in your AppHost
    • -
    • Using the [RestService] Attribute on your Request DTOs
    • +
    • Using the MVC-like Routes config property in your AppHost
    • +
    • Using the [RestService] Attribute on your Request DTOs

    - -

    e.g: the following mapping:

    -

    [RestService("/hello/{Name}")]

    - Allows this web service to be called with: - /servicestack/hello/World! + e.g: the following mapping:

    +

    + [Route("/hello/{Name}")]

    +

    + Allows this web service to be called with: + /api/hello/World!

    - Just like the other endpoints, REST-ful urls can also be called with a HTML FORM POST. - However in this case we need to define another mapping so it matches the url that we want, i.e. + Just like the other endpoints, REST-ful urls can also be called with a HTML FORM + POST. However in this case we need to define another mapping so it matches the url + that we want, i.e.

    -

    [RestService("/hello")]

    +

    + [Route("/hello")]

    Which lets us now call this web service using the following HTML:

    -<form action="servicestack/hello" method="post"> - <label>Name:</label> - <input type="text" name="Name" value="World!"> - <input type="submit"> -</form> - + <form action="api/hello?format=json" method="post"> +   <label>Name:</label> +   <input type="text" name="Name" value="World!" /> +   <input type="submit" /> +</form>

    Example:

    - - - + + +

    - This makes it very easy to Ajax-ify your existing HTML forms, cleanly, - without messy configuration and generated code mandated by other options. + This makes it very easy to Ajax-ify your existing HTML forms, cleanly, without messy + configuration and generated code mandated by other options.

    - -

    Download the code

    + +

    + Calling Web Services from Code

    - Hopefully this tutorial shows just how easy it is to get started and quickly build - web services with Service Stack. + Using DTOs to define your web service interface makes it possible to provide strong-typed + generic service clients without any code-gen or extra build-steps, leading to a + productive end-to-end type-safe communication gateway from client to server.

    - The complete source code for this example is - viewable online - or available to download as zip package from the link below: - - - Download ServiceStack.Examples.zip - - - powered by mono + All REST and ServiceClients share the same interfaces so they can easily be replaced + (for increased perf/debuggability/etc) with a single line of code as seen in the + + Hello Service Integration tests. +

    +

    + C#/.NET Clients can call the above Hello Service using any of the + JSON, JSV, XML or SOAP Service Clients as well as a + Silverlight, + JavaScript, + Dart or even + MQ Client. + +

    + Where to now?

    +

    + Northwind Database Examples

    +

    + Now that you've got the hang of how easy it is to create a simple web service, check + out the Northwind Database + examples to see how useful servicestack becomes with just a little db code.

    - - + + diff --git a/src/ServiceStack.Hello/packages.config b/src/ServiceStack.Hello/packages.config new file mode 100644 index 00000000..6b7d575f --- /dev/null +++ b/src/ServiceStack.Hello/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/Global.asax.cs b/src/ServiceStack.MovieRest/Global.asax.cs deleted file mode 100644 index 276ab590..00000000 --- a/src/ServiceStack.MovieRest/Global.asax.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using Funq; -using ServiceStack.Common.Utils; -using ServiceStack.OrmLite; -using ServiceStack.OrmLite.Sqlite; -using ServiceStack.WebHost.Endpoints; - -namespace ServiceStack.MovieRest -{ - public class AppHost - : AppHostBase - { - public AppHost() - : base("ServiceStack REST at the Movies!", typeof(MovieService).Assembly) {} - - public override void Configure(Container container) - { - container.Register(c => - new OrmLiteConnectionFactory( - "~/App_Data/db.sqlite".MapHostAbsolutePath(), - SqliteOrmLiteDialectProvider.Instance)); - - var resetMovies = container.Resolve(); - resetMovies.Post(null); - - Routes - .Add("/movies", "POST,PUT") - .Add("/movies/{Id}") - .Add("/movies") - .Add("/movies/genres/{Genre}"); - } - } - - public class Global : System.Web.HttpApplication - { - protected void Application_Start(object sender, EventArgs e) - { - new AppHost().Init(); - } - } -} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/MovieService.cs b/src/ServiceStack.MovieRest/MovieService.cs deleted file mode 100644 index 7ce3828e..00000000 --- a/src/ServiceStack.MovieRest/MovieService.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Net; -using ServiceStack.Common.Extensions; -using ServiceStack.Common.Web; -using ServiceStack.DataAnnotations; -using ServiceStack.OrmLite; -using ServiceStack.ServiceInterface; -using ServiceStack.Text; - -namespace ServiceStack.MovieRest -{ - [Description("GET or DELETE a single movie by Id. Use POST to create a new Movie and PUT to update it")] - public class Movie - { - public Movie() - { - this.Genres = new List(); - } - - [AutoIncrement] - public int Id { get; set; } - public string ImdbId { get; set; } - public string Title { get; set; } - public decimal Rating { get; set; } - public string Director { get; set; } - public DateTime ReleaseDate { get; set; } - public string TagLine { get; set; } - public List Genres { get; set; } - } - - public class MovieResponse - { - public Movie Movie { get; set; } - } - - public class MovieService : RestServiceBase - { - public IDbConnectionFactory DbFactory { get; set; } - - /// - /// GET /movies/{Id} - /// - public override object OnGet(Movie movie) - { - return new MovieResponse - { - Movie = DbFactory.Exec(dbCmd => dbCmd.GetById(movie.Id)) - }; - } - - /// - /// POST /movies - /// - /// returns HTTP Response => - /// 201 Created - /// Location: http://localhost/ServiceStack.MovieRest/movies/{newMovieId} - /// - /// {newMovie DTO in [xml|json|jsv|etc]} - /// - /// - public override object OnPost(Movie movie) - { - var newMovieId = DbFactory.Exec(dbCmd => - { - dbCmd.Insert(movie); - return dbCmd.GetLastInsertId(); - }); - - var newMovie = new MovieResponse { - Movie = DbFactory.Exec(dbCmd => dbCmd.GetById(newMovieId)) - }; - - return new HttpResult(newMovie) - { - StatusCode = HttpStatusCode.Created, - Headers = { - { HttpHeaders.Location, this.RequestContext.AbsoluteUri.WithTrailingSlash() + newMovieId } - } - }; - } - - /// - /// PUT /movies/{id} - /// - public override object OnPut(Movie movie) - { - DbFactory.Exec(dbCmd => dbCmd.Save(movie)); - return null; - } - - /// - /// DELETE /movies/{Id} - /// - public override object OnDelete(Movie request) - { - DbFactory.Exec(dbCmd => dbCmd.DeleteById(request.Id)); - return null; - } - } - - [Description("Find movies by genre, or all movies if no genre is provided")] - public class Movies - { - public string Genre { get; set; } - } - - public class MoviesResponse - { - public List Movies { get; set; } - } - - public class MoviesService : RestServiceBase - { - public IDbConnectionFactory DbFactory { get; set; } - - /// - /// GET /movies - /// GET /movies/genres/{Genre} - /// - public override object OnGet(Movies request) - { - return new MoviesResponse - { - Movies = request.Genre.IsNullOrEmpty() - ? DbFactory.Exec(dbCmd => dbCmd.Select()) - : DbFactory.Exec(dbCmd => dbCmd.Select("Genres LIKE {0}", "%" + request.Genre + "%")) - }; - } - } - -} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/ResetMovies.cs b/src/ServiceStack.MovieRest/ResetMovies.cs deleted file mode 100644 index d7d92ca4..00000000 --- a/src/ServiceStack.MovieRest/ResetMovies.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.Serialization; -using ServiceStack.OrmLite; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface; - -namespace ServiceStack.MovieRest -{ - [RestService("/reset-movies")] - [Description("Resets the database back to the original Top 5 movies.")] - [DataContract] public class ResetMovies { } - [DataContract] public class ResetMoviesResponse { } - - public class ResetMoviesService : RestServiceBase - { - public static List Top5Movies = new List - { - new Movie { ImdbId = "tt1375666", Title = "Inception", Rating = 9.2m, Director = "Christopher Nolan", ReleaseDate = new DateTime(2010,7,16), TagLine = "Your mind is the scene of the crime", Genres = new List{"Action", "Thriller", "Sci-Fi"}, }, - new Movie { ImdbId = "tt0111161", Title = "The Shawshank Redemption", Rating = 9.2m, Director = "Frank Darabont", ReleaseDate = new DateTime(1995,2,17), TagLine = "Fear can hold you prisoner. Hope can set you free.", Genres = new List{"Crime", "Drama"}, }, - new Movie { ImdbId = "tt0071562", Title = "The Godfather: Part II", Rating = 9.0m, Director = "Francis Ford Coppola", ReleaseDate = new DateTime(1974,12,20), Genres = new List {"Crime","Drama", "Thriller"}, }, - new Movie { ImdbId = "tt0068646", Title = "The Godfather", Rating = 9.2m, Director = "Francis Ford Coppola", ReleaseDate = new DateTime(1972,3,24), TagLine = "An offer you can't refuse.", Genres = new List {"Crime", "Drama", "Thriller"}, }, - new Movie { ImdbId = "tt0060196", Title = "The Good, the Bad and the Ugly", Rating = 9.0m, Director = "Sergio Leone", ReleaseDate = new DateTime(1967,12,29), TagLine = "They formed an alliance of hate to steal a fortune in dead man's gold", Genres = new List{"Adventure","Western"}, }, - }; - - public IDbConnectionFactory DbFactory { get; set; } - - public override object OnPost(ResetMovies request) - { - DbFactory.Exec(dbCmd => - { - const bool overwriteTable = true; - dbCmd.CreateTable(overwriteTable); - dbCmd.SaveAll(Top5Movies); - }); - - return new ResetMoviesResponse(); - } - } - -} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/ServiceStack.MovieRest.csproj b/src/ServiceStack.MovieRest/ServiceStack.MovieRest.csproj deleted file mode 100644 index cd6b426e..00000000 --- a/src/ServiceStack.MovieRest/ServiceStack.MovieRest.csproj +++ /dev/null @@ -1,144 +0,0 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - ServiceStack.MovieRest - ServiceStack.MovieRest - v3.5 - - - 3.5 - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - x86 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - AllRules.ruleset - x86 - - - - ..\..\lib\Mono.Data.Sqlite.dll - - - ..\..\lib\ServiceStack.dll - - - ..\..\lib\ServiceStack.Common.dll - - - ..\..\lib\ServiceStack.Interfaces.dll - - - ..\..\lib\ServiceStack.OrmLite.dll - - - ..\..\lib\ServiceStack.OrmLite.Sqlite.dll - - - ..\..\lib\ServiceStack.ServiceInterface.dll - - - ..\..\lib\ServiceStack.Text.dll - - - - - 3.5 - - - 3.5 - - - 3.0 - - - 3.5 - - - 3.5 - - - - - - - - - - - sqlite3.dll - PreserveNewest - - - - - - - - - - Designer - - - - - - - Global.asax - - - - - - - - - - - - - - True - True - 55867 - / - http://localhost/ServiceStack.MovieRest - False - False - - - False - - - - - \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/ServiceStack.MovieRest.sln b/src/ServiceStack.MovieRest/ServiceStack.MovieRest.sln index c91ca454..478b505f 100644 --- a/src/ServiceStack.MovieRest/ServiceStack.MovieRest.sln +++ b/src/ServiceStack.MovieRest/ServiceStack.MovieRest.sln @@ -1,20 +1,30 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.MovieRest", "ServiceStack.MovieRest.csproj", "{EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack.MovieRest", "Web\ServiceStack.MovieRest.csproj", "{EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{5C8E3CA4-FE3E-4E64-B089-047A8DC53974}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE3EB8BB-A24E-4F71-8277-1C6DAE652E2C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(CodealikeProperties) = postSolution + SolutionGuid = e2c4be4e-fd9d-4744-8aa5-3a4c14aca0ef + EndGlobalSection +EndGlobal diff --git a/src/ServiceStack.MovieRest/Web.config b/src/ServiceStack.MovieRest/Web.config deleted file mode 100644 index 3a25c46f..00000000 --- a/src/ServiceStack.MovieRest/Web.config +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -
    - -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ServiceStack.MovieRest/Web/App_Start/AppHost.cs b/src/ServiceStack.MovieRest/Web/App_Start/AppHost.cs new file mode 100644 index 00000000..fa7840fb --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/App_Start/AppHost.cs @@ -0,0 +1,39 @@ + +namespace ServiceStack.MovieRest.App_Start +{ + using Funq; + using OrmLite; + using Text; + using Data; + + public class AppHost + : AppHostBase + { + /// + /// Initializes a new instance of your ServiceStack application, with the specified name and assembly containing the services. + /// + public AppHost() : base("ServiceStack REST at the Movies!", typeof (MovieService).Assembly) {} + + public override void Configure(Container container) + { + JsConfig.DateHandler = DateHandler.ISO8601; + + //Set JSON web services to return idiomatic JSON camelCase properties + JsConfig.EmitCamelCaseNames = true; + + container.Register( + c => new OrmLiteConnectionFactory("~/App_Data/db.sqlite".MapHostAbsolutePath(), SqliteDialect.Provider)); + + using (var resetMovies = container.Resolve()) + { + resetMovies.Any(null); + } + + Plugins.Add(new CorsFeature()); //Enable CORS + + SetConfig(new HostConfig { + DebugMode = true //Show StackTraces for easier debugging (default auto inferred by Debug/Release builds) + }); + } + } +} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/Web/Content/Css/default.css b/src/ServiceStack.MovieRest/Web/Content/Css/default.css new file mode 100644 index 00000000..48f5dc47 --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/Content/Css/default.css @@ -0,0 +1,171 @@ +BODY { + background: #fff url(../Images/bg-body-1024.png) repeat-y top left; + font: normal normal normal 13.34px/normal helvetica, arial, freesans, clean, sans-serif; + padding: 0 5px 20px 10px; + width: 940px; +} + +A IMG { + border: none; +} + +#header-links { + top: 10px; + left: 270px; + position: absolute; +} + + #header-links A, #footer-links A { + color: #00F; + margin-left: 0.5em; + } + +code { + background-color: ghostWhite !important; + border: 1px solid #DEDEDE !important; + color: #444 !important; + font-size: 12px !important; + line-height: 1.5em !important; + margin: 1em 0 !important; + overflow: auto !important; + padding: 0.5em !important; + display: block; + font-family: monospace; + white-space: pre; +} + +H1 { + font-size: 170% !important; + margin-top: 0.65em; + padding-top: 0.5em; +} + +H2 { + border-top: 4px solid #E0E0E0 !important; + font-size: 150% !important; + margin-top: 1.5em !important; + padding-top: 0.5em !important; +} + +INPUT[type=text] { + width: 400px; + padding: 2px 5px; +} + +.lnk-src { + padding: 26px 17px 0 0; + float: right; +} + +.ib { + position: relative; + display: -moz-inline-box; + display: inline-block; +} + +* html .ib { + display: inline; +} + +*:first-child + html .ib { + display: inline; +} + +H1 A { + background: url(http://www.servicestack.net/logo-servicestack.png) no-repeat; + display: block; + height: 40px; + padding: 70px 30px 0 120px; + color: #051; + margin: 0 50px 20px 0; + text-decoration: none; +} + +#summary { + margin: 0 0 20px 0; + padding: 10px; + background: #ffc; + color: green; + font-size: 16px; + border: solid 1px #ccc; + font-weight: bold; + text-align: center; +} + + #summary A { + color: #00F; + } + + #summary B { + } + +#btnReset { + float: right; + margin: 20px 0 0 0; +} + +DT { + margin: 10px 0 5px 0; +} + +#existing-movies DD LABEL { + width: 300px; +} + +.lnk-update, .lnk-delete { + margin-left: 10px; + color: #00F; + text-decoration: underline; + cursor: pointer; +} + +H4 { + position: absolute; + top: 270px; + left: 580px; +} + +#restlog { + position: absolute; + top: 290px; + left: 580px; + width: 360px; + height: 600px; + overflow-y: scroll; + font-size: 14px !important; + line-height: 18px !important; +} + + #restlog B { + width: 70px; + } + +FORM { + display: none; +} + +SELECT[name=genres] { + padding: 4px; + position: absolute; + left: 345px; + margin-top: 20px; +} + +#btn-download { + display: block; + border-top: solid 4px #E0E0E0; + margin: 20px 0 20px 0px; + padding: 10px 0 0 0; +} + +#csvformat { + background: url(http://www.servicestack.net/excel16x16.gif) no-repeat top left; + padding: 0 0 0 20px; + margin: 15px 0 0 0; +} + + #csvformat B { + color: #00f; + text-decoration: underline; + cursor: pointer; + } diff --git a/src/ServiceStack.MovieRest/img/bg-body-1024.png b/src/ServiceStack.MovieRest/Web/Content/Images/bg-body-1024.png similarity index 52% rename from src/ServiceStack.MovieRest/img/bg-body-1024.png rename to src/ServiceStack.MovieRest/Web/Content/Images/bg-body-1024.png index b7a28a44..eb00431e 100644 Binary files a/src/ServiceStack.MovieRest/img/bg-body-1024.png and b/src/ServiceStack.MovieRest/Web/Content/Images/bg-body-1024.png differ diff --git a/src/ServiceStack.MovieRest/Web/Content/Images/btn-github.png b/src/ServiceStack.MovieRest/Web/Content/Images/btn-github.png new file mode 100644 index 00000000..1cec3751 Binary files /dev/null and b/src/ServiceStack.MovieRest/Web/Content/Images/btn-github.png differ diff --git a/src/ServiceStack.MovieRest/Global.asax b/src/ServiceStack.MovieRest/Web/Global.asax similarity index 100% rename from src/ServiceStack.MovieRest/Global.asax rename to src/ServiceStack.MovieRest/Web/Global.asax diff --git a/src/ServiceStack.MovieRest/Web/Global.asax.cs b/src/ServiceStack.MovieRest/Web/Global.asax.cs new file mode 100644 index 00000000..8e1908ed --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/Global.asax.cs @@ -0,0 +1,16 @@ +using System; +using ServiceStack.MovieRest.App_Start; + +namespace ServiceStack.MovieRest +{ + using System.Web; + + public class Global : HttpApplication + { + protected void Application_Start(object sender, EventArgs e) + { + //Initialize your application + (new AppHost()).Init(); + } + } +} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/Web/MovieService.cs b/src/ServiceStack.MovieRest/Web/MovieService.cs new file mode 100644 index 00000000..2b8adc16 --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/MovieService.cs @@ -0,0 +1,167 @@ +using System.Runtime.Serialization; + +namespace ServiceStack.MovieRest +{ + using System; + using System.Collections.Generic; + using System.Net; + using DataAnnotations; + using OrmLite; + + /// + /// Define your ServiceStack web service request (i.e. Request DTO). + /// + /// The route is defined here rather than in the AppHost. + [Api("GET or DELETE a single movie by Id. Use POST to create a new Movie and PUT to update it")] + [Route("/movies", "POST,PUT,PATCH,DELETE")] + [Route("/movies/{Id}")] + public class Movie : IReturn + { + /// + /// Initializes a new instance of the movie. + /// + public Movie() + { + this.Genres = new List(); + } + + /// + /// Gets or sets the id of the movie. The id will be automatically incremented when added. + /// + [AutoIncrement] + public int Id { get; set; } + + public string ImdbId { get; set; } + public string Title { get; set; } + public decimal Rating { get; set; } + public string Director { get; set; } + public DateTime ReleaseDate { get; set; } + public string TagLine { get; set; } + public List Genres { get; set; } + } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + public class MovieResponse + { + /// + /// Gets or sets the movie. + /// + public Movie Movie { get; set; } + } + + /// + /// Define your ServiceStack web service request (i.e. Request DTO). + /// + /// The route is defined here rather than in the AppHost. + [Api("Find movies by genre, or all movies if no genre is provided")] + [Route("/movies", "GET, OPTIONS")] + [Route("/movies/genres/{Genre}")] + public class Movies : IReturn + { + public string Genre { get; set; } + } + + /// + /// Define your ServiceStack web service response (i.e. Response DTO). + /// + [DataContract] + public class MoviesResponse + { + /// + /// Gets or sets the list of movies. + /// + [DataMember] + public List Movies { get; set; } + } + + /// + /// Create your ServiceStack restful web service implementation. + /// + public class MovieService : Service + { + /// + /// GET /movies + /// GET /movies/genres/{Genre} + /// + public object Get(Movies request) + { + return new MoviesResponse { + Movies = request.Genre.IsNullOrEmpty() + ? Db.Select() + : Db.Select("Genres LIKE {0}", "%{0}%".Fmt(request.Genre)) + }; + } + + /// + /// GET /movies/{Id} + /// + public MovieResponse Get(Movie movie) + { + return new MovieResponse + { + Movie = Db.SingleById(movie.Id), + }; + } + + /// + /// POST /movies + /// returns HTTP Response => + /// 201 Created + /// Location: http://localhost/ServiceStack.MovieRest/movies/{newMovieId} + /// {newMovie DTO in [xml|json|jsv|etc]} + /// + public object Post(Movie movie) + { + Db.Save(movie); + var newMovieId = movie.Id; + + var newMovie = new MovieResponse + { + Movie = Db.SingleById(newMovieId), + }; + + return new HttpResult(newMovie) + { + StatusCode = HttpStatusCode.Created, + Headers = { + {HttpHeaders.Location, base.Request.AbsoluteUri.CombineWith(newMovieId.ToString())} + } + }; + } + + /// + /// PUT /movies/{id} + /// + public object Put(Movie movie) + { + Db.Update(movie); + + return new HttpResult + { + StatusCode = HttpStatusCode.NoContent, + Headers = + { + {HttpHeaders.Location, this.Request.AbsoluteUri.CombineWith(movie.Id.ToString())} + } + }; + } + + /// + /// DELETE /movies/{Id} + /// + public object Delete(Movie request) + { + Db.DeleteById(request.Id); + + return new HttpResult + { + StatusCode = HttpStatusCode.NoContent, + Headers = { + {HttpHeaders.Location, this.Request.AbsoluteUri.CombineWith(request.Id.ToString())} + } + }; + } + } +} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/Properties/AssemblyInfo.cs b/src/ServiceStack.MovieRest/Web/Properties/AssemblyInfo.cs similarity index 91% rename from src/ServiceStack.MovieRest/Properties/AssemblyInfo.cs rename to src/ServiceStack.MovieRest/Web/Properties/AssemblyInfo.cs index 181ae82d..8d9ec20c 100644 --- a/src/ServiceStack.MovieRest/Properties/AssemblyInfo.cs +++ b/src/ServiceStack.MovieRest/Web/Properties/AssemblyInfo.cs @@ -1,40 +1,40 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ServiceStack.MovieRest")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ServiceStack.MovieRest")] -[assembly: AssemblyCopyright("Copyright © 2010")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] - -[assembly: ContractNamespace("http://schemas.servicestack.net/types", - ClrNamespace = "ServiceStack.MovieRest")] - +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ServiceStack.MovieRest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ServiceStack.MovieRest")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.1.1205.1037")] +[assembly: AssemblyFileVersion("1.1.1205.1037")] + +[assembly: ContractNamespace("http://schemas.servicestack.net/types", + ClrNamespace = "ServiceStack.MovieRest")] + diff --git a/src/ServiceStack.MovieRest/Web/ResetMovies.cs b/src/ServiceStack.MovieRest/Web/ResetMovies.cs new file mode 100644 index 00000000..5971b0a6 --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/ResetMovies.cs @@ -0,0 +1,80 @@ +namespace ServiceStack.MovieRest +{ + using System; + using System.Collections.Generic; + using OrmLite; + + /// + /// Define your ServiceStack web service request (i.e. Request DTO). + /// + /// The route is defined here rather than in the AppHost. + [Route("/reset-movies", "GET,POST")] + [Api("Resets the database back to the original Top 5 movies.")] + public class ResetMovies : IReturnVoid {} + + /// + /// Create your ServiceStack rest-ful web service implementation. + /// + public class ResetMoviesService : Service + { + public static List Top5Movies = new List { + new Movie + { + ImdbId = "tt1375666", + Title = "Inception", + Rating = 9.2m, + Director = "Christopher Nolan", + ReleaseDate = new DateTime(2010, 7, 16), + TagLine = "Your mind is the scene of the crime", + Genres = new List {"Action", "Thriller", "Sci-Fi"}, + }, + new Movie + { + ImdbId = "tt0111161", + Title = "The Shawshank Redemption", + Rating = 9.2m, + Director = "Frank Darabont", + ReleaseDate = new DateTime(1995, 2, 17), + TagLine = "Fear can hold you prisoner. Hope can set you free.", + Genres = new List {"Crime", "Drama"}, + }, + new Movie + { + ImdbId = "tt0071562", + Title = "The Godfather: Part II", + Rating = 9.0m, + Director = "Francis Ford Coppola", + ReleaseDate = new DateTime(1974, 12, 20), + Genres = new List {"Crime", "Drama", "Thriller"}, + }, + new Movie + { + ImdbId = "tt0068646", + Title = "The Godfather", + Rating = 9.2m, + Director = "Francis Ford Coppola", + ReleaseDate = new DateTime(1972, 3, 24), + TagLine = "An offer you can't refuse.", + Genres = new List {"Crime", "Drama", "Thriller"}, + }, + new Movie + { + ImdbId = "tt0060196", + Title = "The Good, the Bad and the Ugly", + Rating = 9.0m, + Director = "Sergio Leone", + ReleaseDate = new DateTime(1967, 12, 29), + TagLine = + "They formed an alliance of hate to steal a fortune in dead man's gold", + Genres = new List {"Adventure", "Western"}, + }, + }; + + public void Any(ResetMovies request) + { + //Executes the specified delegate against the configured database. + Db.DropAndCreateTable(); + Db.SaveAll(Top5Movies); + } + } +} \ No newline at end of file diff --git a/src/ServiceStack.MovieRest/Web/Scripts/jquery-1.10.2.intellisense.js b/src/ServiceStack.MovieRest/Web/Scripts/jquery-1.10.2.intellisense.js new file mode 100644 index 00000000..bb46fb2b --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/Scripts/jquery-1.10.2.intellisense.js @@ -0,0 +1,2657 @@ +intellisense.annotate(jQuery, { + 'ajax': function() { + /// + /// Perform an asynchronous HTTP (Ajax) request. + /// A string containing the URL to which the request is sent. + /// A set of key/value pairs that configure the Ajax request. All settings are optional. A default can be set for any option with $.ajaxSetup(). See jQuery.ajax( settings ) below for a complete list of all settings. + /// + /// + /// + /// Perform an asynchronous HTTP (Ajax) request. + /// A set of key/value pairs that configure the Ajax request. All settings are optional. A default can be set for any option with $.ajaxSetup(). + /// + /// + }, + 'ajaxPrefilter': function() { + /// + /// Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax(). + /// An optional string containing one or more space-separated dataTypes + /// A handler to set default values for future Ajax requests. + /// + }, + 'ajaxSetup': function() { + /// + /// Set default values for future Ajax requests. + /// A set of key/value pairs that configure the default Ajax request. All options are optional. + /// + }, + 'ajaxTransport': function() { + /// + /// Creates an object that handles the actual transmission of Ajax data. + /// A string identifying the data type to use + /// A handler to return the new transport object to use with the data type provided in the first argument. + /// + }, + 'boxModel': function() { + /// Deprecated in jQuery 1.3 (see jQuery.support). States if the current page, in the user's browser, is being rendered using the W3C CSS Box Model. + /// + }, + 'browser': function() { + /// Contains flags for the useragent, read from navigator.userAgent. We recommend against using this property; please try to use feature detection instead (see jQuery.support). jQuery.browser may be moved to a plugin in a future release of jQuery. + /// + }, + 'browser.version': function() { + /// The version number of the rendering engine for the user's browser. + /// + }, + 'Callbacks': function() { + /// + /// A multi-purpose callbacks list object that provides a powerful way to manage callback lists. + /// An optional list of space-separated flags that change how the callback list behaves. + /// + /// + }, + 'contains': function() { + /// + /// Check to see if a DOM element is a descendant of another DOM element. + /// The DOM element that may contain the other element. + /// The DOM element that may be contained by (a descendant of) the other element. + /// + /// + }, + 'cssHooks': function() { + /// Hook directly into jQuery to override how particular CSS properties are retrieved or set, normalize CSS property naming, or create custom properties. + /// + }, + 'data': function() { + /// + /// Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element. + /// The DOM element to query for the data. + /// Name of the data stored. + /// + /// + /// + /// Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element. + /// The DOM element to query for the data. + /// + /// + }, + 'Deferred': function() { + /// + /// A constructor function that returns a chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function. + /// A function that is called just before the constructor returns. + /// + /// + }, + 'dequeue': function() { + /// + /// Execute the next function on the queue for the matched element. + /// A DOM element from which to remove and execute a queued function. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// + }, + 'each': function() { + /// + /// A generic iterator function, which can be used to seamlessly iterate over both objects and arrays. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties. + /// The object or array to iterate over. + /// The function that will be executed on every object. + /// + /// + }, + 'error': function() { + /// + /// Takes a string and throws an exception containing it. + /// The message to send out. + /// + }, + 'extend': function() { + /// + /// Merge the contents of two or more objects together into the first object. + /// An object that will receive the new properties if additional objects are passed in or that will extend the jQuery namespace if it is the sole argument. + /// An object containing additional properties to merge in. + /// Additional objects containing properties to merge in. + /// + /// + /// + /// Merge the contents of two or more objects together into the first object. + /// If true, the merge becomes recursive (aka. deep copy). + /// The object to extend. It will receive the new properties. + /// An object containing additional properties to merge in. + /// Additional objects containing properties to merge in. + /// + /// + }, + 'get': function() { + /// + /// Load data from the server using a HTTP GET request. + /// A string containing the URL to which the request is sent. + /// A plain object or string that is sent to the server with the request. + /// A callback function that is executed if the request succeeds. + /// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html). + /// + /// + }, + 'getJSON': function() { + /// + /// Load JSON-encoded data from the server using a GET HTTP request. + /// A string containing the URL to which the request is sent. + /// A plain object or string that is sent to the server with the request. + /// A callback function that is executed if the request succeeds. + /// + /// + }, + 'getScript': function() { + /// + /// Load a JavaScript file from the server using a GET HTTP request, then execute it. + /// A string containing the URL to which the request is sent. + /// A callback function that is executed if the request succeeds. + /// + /// + }, + 'globalEval': function() { + /// + /// Execute some JavaScript code globally. + /// The JavaScript code to execute. + /// + }, + 'grep': function() { + /// + /// Finds the elements of an array which satisfy a filter function. The original array is not affected. + /// The array to search through. + /// The function to process each item against. The first argument to the function is the item, and the second argument is the index. The function should return a Boolean value. this will be the global window object. + /// If "invert" is false, or not provided, then the function returns an array consisting of all elements for which "callback" returns true. If "invert" is true, then the function returns an array consisting of all elements for which "callback" returns false. + /// + /// + }, + 'hasData': function() { + /// + /// Determine whether an element has any jQuery data associated with it. + /// A DOM element to be checked for data. + /// + /// + }, + 'holdReady': function() { + /// + /// Holds or releases the execution of jQuery's ready event. + /// Indicates whether the ready hold is being requested or released + /// + }, + 'inArray': function() { + /// + /// Search for a specified value within an array and return its index (or -1 if not found). + /// The value to search for. + /// An array through which to search. + /// The index of the array at which to begin the search. The default is 0, which will search the whole array. + /// + /// + }, + 'isArray': function() { + /// + /// Determine whether the argument is an array. + /// Object to test whether or not it is an array. + /// + /// + }, + 'isEmptyObject': function() { + /// + /// Check to see if an object is empty (contains no enumerable properties). + /// The object that will be checked to see if it's empty. + /// + /// + }, + 'isFunction': function() { + /// + /// Determine if the argument passed is a Javascript function object. + /// Object to test whether or not it is a function. + /// + /// + }, + 'isNumeric': function() { + /// + /// Determines whether its argument is a number. + /// The value to be tested. + /// + /// + }, + 'isPlainObject': function() { + /// + /// Check to see if an object is a plain object (created using "{}" or "new Object"). + /// The object that will be checked to see if it's a plain object. + /// + /// + }, + 'isWindow': function() { + /// + /// Determine whether the argument is a window. + /// Object to test whether or not it is a window. + /// + /// + }, + 'isXMLDoc': function() { + /// + /// Check to see if a DOM node is within an XML document (or is an XML document). + /// The DOM node that will be checked to see if it's in an XML document. + /// + /// + }, + 'makeArray': function() { + /// + /// Convert an array-like object into a true JavaScript array. + /// Any object to turn into a native Array. + /// + /// + }, + 'map': function() { + /// + /// Translate all items in an array or object to new array of items. + /// The Array to translate. + /// The function to process each item against. The first argument to the function is the array item, the second argument is the index in array The function can return any value. Within the function, this refers to the global (window) object. + /// + /// + /// + /// Translate all items in an array or object to new array of items. + /// The Array or Object to translate. + /// The function to process each item against. The first argument to the function is the value; the second argument is the index or key of the array or object property. The function can return any value to add to the array. A returned array will be flattened into the resulting array. Within the function, this refers to the global (window) object. + /// + /// + }, + 'merge': function() { + /// + /// Merge the contents of two arrays together into the first array. + /// The first array to merge, the elements of second added. + /// The second array to merge into the first, unaltered. + /// + /// + }, + 'noConflict': function() { + /// + /// Relinquish jQuery's control of the $ variable. + /// A Boolean indicating whether to remove all jQuery variables from the global scope (including jQuery itself). + /// + /// + }, + 'noop': function() { + /// An empty function. + }, + 'now': function() { + /// Return a number representing the current time. + /// + }, + 'param': function() { + /// + /// Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request. + /// An array or object to serialize. + /// + /// + /// + /// Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request. + /// An array or object to serialize. + /// A Boolean indicating whether to perform a traditional "shallow" serialization. + /// + /// + }, + 'parseHTML': function() { + /// + /// Parses a string into an array of DOM nodes. + /// HTML string to be parsed + /// DOM element to serve as the context in which the HTML fragment will be created + /// A Boolean indicating whether to include scripts passed in the HTML string + /// + /// + }, + 'parseJSON': function() { + /// + /// Takes a well-formed JSON string and returns the resulting JavaScript object. + /// The JSON string to parse. + /// + /// + }, + 'parseXML': function() { + /// + /// Parses a string into an XML document. + /// a well-formed XML string to be parsed + /// + /// + }, + 'post': function() { + /// + /// Load data from the server using a HTTP POST request. + /// A string containing the URL to which the request is sent. + /// A plain object or string that is sent to the server with the request. + /// A callback function that is executed if the request succeeds. + /// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, text, html). + /// + /// + }, + 'proxy': function() { + /// + /// Takes a function and returns a new one that will always have a particular context. + /// The function whose context will be changed. + /// The object to which the context (this) of the function should be set. + /// + /// + /// + /// Takes a function and returns a new one that will always have a particular context. + /// The object to which the context of the function should be set. + /// The name of the function whose context will be changed (should be a property of the context object). + /// + /// + /// + /// Takes a function and returns a new one that will always have a particular context. + /// The function whose context will be changed. + /// The object to which the context (this) of the function should be set. + /// Any number of arguments to be passed to the function referenced in the function argument. + /// + /// + /// + /// Takes a function and returns a new one that will always have a particular context. + /// The object to which the context of the function should be set. + /// The name of the function whose context will be changed (should be a property of the context object). + /// Any number of arguments to be passed to the function named in the name argument. + /// + /// + }, + 'queue': function() { + /// + /// Manipulate the queue of functions to be executed on the matched element. + /// A DOM element where the array of queued functions is attached. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// An array of functions to replace the current queue contents. + /// + /// + /// + /// Manipulate the queue of functions to be executed on the matched element. + /// A DOM element on which to add a queued function. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// The new function to add to the queue. + /// + /// + }, + 'removeData': function() { + /// + /// Remove a previously-stored piece of data. + /// A DOM element from which to remove data. + /// A string naming the piece of data to remove. + /// + /// + }, + 'sub': function() { + /// Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object. + /// + }, + 'support': function() { + /// A collection of properties that represent the presence of different browser features or bugs. Primarily intended for jQuery's internal use; specific properties may be removed when they are no longer needed internally to improve page startup performance. + /// + }, + 'trim': function() { + /// + /// Remove the whitespace from the beginning and end of a string. + /// The string to trim. + /// + /// + }, + 'type': function() { + /// + /// Determine the internal JavaScript [[Class]] of an object. + /// Object to get the internal JavaScript [[Class]] of. + /// + /// + }, + 'unique': function() { + /// + /// Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers. + /// The Array of DOM elements. + /// + /// + }, + 'when': function() { + /// + /// Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events. + /// One or more Deferred objects, or plain JavaScript objects. + /// + /// + }, +}); + +var _1228819969 = jQuery.Callbacks; +jQuery.Callbacks = function(flags) { +var _object = _1228819969(flags); +intellisense.annotate(_object, { + 'add': function() { + /// + /// Add a callback or a collection of callbacks to a callback list. + /// A function, or array of functions, that are to be added to the callback list. + /// + /// + }, + 'disable': function() { + /// Disable a callback list from doing anything more. + /// + }, + 'disabled': function() { + /// Determine if the callbacks list has been disabled. + /// + }, + 'empty': function() { + /// Remove all of the callbacks from a list. + /// + }, + 'fire': function() { + /// + /// Call all of the callbacks with the given arguments + /// The argument or list of arguments to pass back to the callback list. + /// + /// + }, + 'fired': function() { + /// Determine if the callbacks have already been called at least once. + /// + }, + 'fireWith': function() { + /// + /// Call all callbacks in a list with the given context and arguments. + /// A reference to the context in which the callbacks in the list should be fired. + /// An argument, or array of arguments, to pass to the callbacks in the list. + /// + /// + }, + 'has': function() { + /// + /// Determine whether a supplied callback is in a list + /// The callback to search for. + /// + /// + }, + 'lock': function() { + /// Lock a callback list in its current state. + /// + }, + 'locked': function() { + /// Determine if the callbacks list has been locked. + /// + }, + 'remove': function() { + /// + /// Remove a callback or a collection of callbacks from a callback list. + /// A function, or array of functions, that are to be removed from the callback list. + /// + /// + }, +}); + +return _object; +}; +intellisense.redirectDefinition(jQuery.Callbacks, _1228819969); + +var _731531622 = jQuery.Deferred; +jQuery.Deferred = function(func) { +var _object = _731531622(func); +intellisense.annotate(_object, { + 'always': function() { + /// + /// Add handlers to be called when the Deferred object is either resolved or rejected. + /// A function, or array of functions, that is called when the Deferred is resolved or rejected. + /// Optional additional functions, or arrays of functions, that are called when the Deferred is resolved or rejected. + /// + /// + }, + 'done': function() { + /// + /// Add handlers to be called when the Deferred object is resolved. + /// A function, or array of functions, that are called when the Deferred is resolved. + /// Optional additional functions, or arrays of functions, that are called when the Deferred is resolved. + /// + /// + }, + 'fail': function() { + /// + /// Add handlers to be called when the Deferred object is rejected. + /// A function, or array of functions, that are called when the Deferred is rejected. + /// Optional additional functions, or arrays of functions, that are called when the Deferred is rejected. + /// + /// + }, + 'isRejected': function() { + /// Determine whether a Deferred object has been rejected. + /// + }, + 'isResolved': function() { + /// Determine whether a Deferred object has been resolved. + /// + }, + 'notify': function() { + /// + /// Call the progressCallbacks on a Deferred object with the given args. + /// Optional arguments that are passed to the progressCallbacks. + /// + /// + }, + 'notifyWith': function() { + /// + /// Call the progressCallbacks on a Deferred object with the given context and args. + /// Context passed to the progressCallbacks as the this object. + /// Optional arguments that are passed to the progressCallbacks. + /// + /// + }, + 'pipe': function() { + /// + /// Utility method to filter and/or chain Deferreds. + /// An optional function that is called when the Deferred is resolved. + /// An optional function that is called when the Deferred is rejected. + /// + /// + /// + /// Utility method to filter and/or chain Deferreds. + /// An optional function that is called when the Deferred is resolved. + /// An optional function that is called when the Deferred is rejected. + /// An optional function that is called when progress notifications are sent to the Deferred. + /// + /// + }, + 'progress': function() { + /// + /// Add handlers to be called when the Deferred object generates progress notifications. + /// A function, or array of functions, that is called when the Deferred generates progress notifications. + /// + /// + }, + 'promise': function() { + /// + /// Return a Deferred's Promise object. + /// Object onto which the promise methods have to be attached + /// + /// + }, + 'reject': function() { + /// + /// Reject a Deferred object and call any failCallbacks with the given args. + /// Optional arguments that are passed to the failCallbacks. + /// + /// + }, + 'rejectWith': function() { + /// + /// Reject a Deferred object and call any failCallbacks with the given context and args. + /// Context passed to the failCallbacks as the this object. + /// An optional array of arguments that are passed to the failCallbacks. + /// + /// + }, + 'resolve': function() { + /// + /// Resolve a Deferred object and call any doneCallbacks with the given args. + /// Optional arguments that are passed to the doneCallbacks. + /// + /// + }, + 'resolveWith': function() { + /// + /// Resolve a Deferred object and call any doneCallbacks with the given context and args. + /// Context passed to the doneCallbacks as the this object. + /// An optional array of arguments that are passed to the doneCallbacks. + /// + /// + }, + 'state': function() { + /// Determine the current state of a Deferred object. + /// + }, + 'then': function() { + /// + /// Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. + /// A function that is called when the Deferred is resolved. + /// An optional function that is called when the Deferred is rejected. + /// An optional function that is called when progress notifications are sent to the Deferred. + /// + /// + /// + /// Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. + /// A function, or array of functions, called when the Deferred is resolved. + /// A function, or array of functions, called when the Deferred is rejected. + /// + /// + /// + /// Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. + /// A function, or array of functions, called when the Deferred is resolved. + /// A function, or array of functions, called when the Deferred is rejected. + /// A function, or array of functions, called when the Deferred notifies progress. + /// + /// + }, +}); + +return _object; +}; +intellisense.redirectDefinition(jQuery.Callbacks, _731531622); + +intellisense.annotate(jQuery.Event.prototype, { + 'currentTarget': function() { + /// The current DOM element within the event bubbling phase. + /// + }, + 'data': function() { + /// An optional object of data passed to an event method when the current executing handler is bound. + /// + }, + 'delegateTarget': function() { + /// The element where the currently-called jQuery event handler was attached. + /// + }, + 'isDefaultPrevented': function() { + /// Returns whether event.preventDefault() was ever called on this event object. + /// + }, + 'isImmediatePropagationStopped': function() { + /// Returns whether event.stopImmediatePropagation() was ever called on this event object. + /// + }, + 'isPropagationStopped': function() { + /// Returns whether event.stopPropagation() was ever called on this event object. + /// + }, + 'metaKey': function() { + /// Indicates whether the META key was pressed when the event fired. + /// + }, + 'namespace': function() { + /// The namespace specified when the event was triggered. + /// + }, + 'pageX': function() { + /// The mouse position relative to the left edge of the document. + /// + }, + 'pageY': function() { + /// The mouse position relative to the top edge of the document. + /// + }, + 'preventDefault': function() { + /// If this method is called, the default action of the event will not be triggered. + }, + 'relatedTarget': function() { + /// The other DOM element involved in the event, if any. + /// + }, + 'result': function() { + /// The last value returned by an event handler that was triggered by this event, unless the value was undefined. + /// + }, + 'stopImmediatePropagation': function() { + /// Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree. + }, + 'stopPropagation': function() { + /// Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event. + }, + 'target': function() { + /// The DOM element that initiated the event. + /// + }, + 'timeStamp': function() { + /// The difference in milliseconds between the time the browser created the event and January 1, 1970. + /// + }, + 'type': function() { + /// Describes the nature of the event. + /// + }, + 'which': function() { + /// For key or mouse events, this property indicates the specific key or button that was pressed. + /// + }, +}); + +intellisense.annotate(jQuery.fn, { + 'add': function() { + /// + /// Add elements to the set of matched elements. + /// A string representing a selector expression to find additional elements to add to the set of matched elements. + /// + /// + /// + /// Add elements to the set of matched elements. + /// One or more elements to add to the set of matched elements. + /// + /// + /// + /// Add elements to the set of matched elements. + /// An HTML fragment to add to the set of matched elements. + /// + /// + /// + /// Add elements to the set of matched elements. + /// An existing jQuery object to add to the set of matched elements. + /// + /// + /// + /// Add elements to the set of matched elements. + /// A string representing a selector expression to find additional elements to add to the set of matched elements. + /// The point in the document at which the selector should begin matching; similar to the context argument of the $(selector, context) method. + /// + /// + }, + 'addBack': function() { + /// + /// Add the previous set of elements on the stack to the current set, optionally filtered by a selector. + /// A string containing a selector expression to match the current set of elements against. + /// + /// + }, + 'addClass': function() { + /// + /// Adds the specified class(es) to each of the set of matched elements. + /// One or more space-separated classes to be added to the class attribute of each matched element. + /// + /// + /// + /// Adds the specified class(es) to each of the set of matched elements. + /// A function returning one or more space-separated class names to be added to the existing class name(s). Receives the index position of the element in the set and the existing class name(s) as arguments. Within the function, this refers to the current element in the set. + /// + /// + }, + 'after': function() { + /// + /// Insert content, specified by the parameter, after each element in the set of matched elements. + /// HTML string, DOM element, or jQuery object to insert after each element in the set of matched elements. + /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert after each element in the set of matched elements. + /// + /// + /// + /// Insert content, specified by the parameter, after each element in the set of matched elements. + /// A function that returns an HTML string, DOM element(s), or jQuery object to insert after each element in the set of matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set. + /// + /// + }, + 'ajaxComplete': function() { + /// + /// Register a handler to be called when Ajax requests complete. This is an AjaxEvent. + /// The function to be invoked. + /// + /// + }, + 'ajaxError': function() { + /// + /// Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event. + /// The function to be invoked. + /// + /// + }, + 'ajaxSend': function() { + /// + /// Attach a function to be executed before an Ajax request is sent. This is an Ajax Event. + /// The function to be invoked. + /// + /// + }, + 'ajaxStart': function() { + /// + /// Register a handler to be called when the first Ajax request begins. This is an Ajax Event. + /// The function to be invoked. + /// + /// + }, + 'ajaxStop': function() { + /// + /// Register a handler to be called when all Ajax requests have completed. This is an Ajax Event. + /// The function to be invoked. + /// + /// + }, + 'ajaxSuccess': function() { + /// + /// Attach a function to be executed whenever an Ajax request completes successfully. This is an Ajax Event. + /// The function to be invoked. + /// + /// + }, + 'all': function() { + /// Selects all elements. + }, + 'andSelf': function() { + /// Add the previous set of elements on the stack to the current set. + /// + }, + 'animate': function() { + /// + /// Perform a custom animation of a set of CSS properties. + /// An object of CSS properties and values that the animation will move toward. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + /// + /// Perform a custom animation of a set of CSS properties. + /// An object of CSS properties and values that the animation will move toward. + /// A map of additional options to pass to the method. + /// + /// + }, + 'animated': function() { + /// Select all elements that are in the progress of an animation at the time the selector is run. + }, + 'append': function() { + /// + /// Insert content, specified by the parameter, to the end of each element in the set of matched elements. + /// DOM element, HTML string, or jQuery object to insert at the end of each element in the set of matched elements. + /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the end of each element in the set of matched elements. + /// + /// + /// + /// Insert content, specified by the parameter, to the end of each element in the set of matched elements. + /// A function that returns an HTML string, DOM element(s), or jQuery object to insert at the end of each element in the set of matched elements. Receives the index position of the element in the set and the old HTML value of the element as arguments. Within the function, this refers to the current element in the set. + /// + /// + }, + 'appendTo': function() { + /// + /// Insert every element in the set of matched elements to the end of the target. + /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the end of the element(s) specified by this parameter. + /// + /// + }, + 'attr': function() { + /// + /// Set one or more attributes for the set of matched elements. + /// The name of the attribute to set. + /// A value to set for the attribute. + /// + /// + /// + /// Set one or more attributes for the set of matched elements. + /// An object of attribute-value pairs to set. + /// + /// + /// + /// Set one or more attributes for the set of matched elements. + /// The name of the attribute to set. + /// A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old attribute value as arguments. + /// + /// + }, + 'attributeContains': function() { + /// + /// Selects elements that have the specified attribute with a value containing the a given substring. + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'attributeContainsPrefix': function() { + /// + /// Selects elements that have the specified attribute with a value either equal to a given string or starting with that string followed by a hyphen (-). + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'attributeContainsWord': function() { + /// + /// Selects elements that have the specified attribute with a value containing a given word, delimited by spaces. + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'attributeEndsWith': function() { + /// + /// Selects elements that have the specified attribute with a value ending exactly with a given string. The comparison is case sensitive. + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'attributeEquals': function() { + /// + /// Selects elements that have the specified attribute with a value exactly equal to a certain value. + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'attributeHas': function() { + /// + /// Selects elements that have the specified attribute, with any value. + /// An attribute name. + /// + }, + 'attributeMultiple': function() { + /// + /// Matches elements that match all of the specified attribute filters. + /// An attribute filter. + /// Another attribute filter, reducing the selection even more + /// As many more attribute filters as necessary + /// + }, + 'attributeNotEqual': function() { + /// + /// Select elements that either don't have the specified attribute, or do have the specified attribute but not with a certain value. + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'attributeStartsWith': function() { + /// + /// Selects elements that have the specified attribute with a value beginning exactly with a given string. + /// An attribute name. + /// An attribute value. Can be either an unquoted single word or a quoted string. + /// + }, + 'before': function() { + /// + /// Insert content, specified by the parameter, before each element in the set of matched elements. + /// HTML string, DOM element, or jQuery object to insert before each element in the set of matched elements. + /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert before each element in the set of matched elements. + /// + /// + /// + /// Insert content, specified by the parameter, before each element in the set of matched elements. + /// A function that returns an HTML string, DOM element(s), or jQuery object to insert before each element in the set of matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set. + /// + /// + }, + 'bind': function() { + /// + /// Attach a handler to an event for the elements. + /// A string containing one or more DOM event types, such as "click" or "submit," or custom event names. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Attach a handler to an event for the elements. + /// A string containing one or more DOM event types, such as "click" or "submit," or custom event names. + /// An object containing data that will be passed to the event handler. + /// Setting the third argument to false will attach a function that prevents the default action from occurring and stops the event from bubbling. The default is true. + /// + /// + /// + /// Attach a handler to an event for the elements. + /// An object containing one or more DOM event types and functions to execute for them. + /// + /// + }, + 'blur': function() { + /// + /// Bind an event handler to the "blur" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "blur" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'button': function() { + /// Selects all button elements and elements of type button. + }, + 'change': function() { + /// + /// Bind an event handler to the "change" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "change" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'checkbox': function() { + /// Selects all elements of type checkbox. + }, + 'checked': function() { + /// Matches all elements that are checked. + }, + 'child': function() { + /// + /// Selects all direct child elements specified by "child" of elements specified by "parent". + /// Any valid selector. + /// A selector to filter the child elements. + /// + }, + 'children': function() { + /// + /// Get the children of each element in the set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'class': function() { + /// + /// Selects all elements with the given class. + /// A class to search for. An element can have multiple classes; only one of them must match. + /// + }, + 'clearQueue': function() { + /// + /// Remove from the queue all items that have not yet been run. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// + /// + }, + 'click': function() { + /// + /// Bind an event handler to the "click" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "click" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'clone': function() { + /// + /// Create a deep copy of the set of matched elements. + /// A Boolean indicating whether event handlers should be copied along with the elements. As of jQuery 1.4, element data will be copied as well. + /// + /// + /// + /// Create a deep copy of the set of matched elements. + /// A Boolean indicating whether event handlers and data should be copied along with the elements. The default value is false. *In jQuery 1.5.0 the default value was incorrectly true; it was changed back to false in 1.5.1 and up. + /// A Boolean indicating whether event handlers and data for all children of the cloned element should be copied. By default its value matches the first argument's value (which defaults to false). + /// + /// + }, + 'closest': function() { + /// + /// For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + /// A string containing a selector expression to match elements against. + /// A DOM element within which a matching element may be found. If no context is passed in then the context of the jQuery set will be used instead. + /// + /// + /// + /// For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + /// A jQuery object to match elements against. + /// + /// + /// + /// For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + /// An element to match elements against. + /// + /// + }, + 'contains': function() { + /// + /// Select all elements that contain the specified text. + /// A string of text to look for. It's case sensitive. + /// + }, + 'contents': function() { + /// Get the children of each element in the set of matched elements, including text and comment nodes. + /// + }, + 'context': function() { + /// The DOM node context originally passed to jQuery(); if none was passed then context will likely be the document. + /// + }, + 'css': function() { + /// + /// Set one or more CSS properties for the set of matched elements. + /// A CSS property name. + /// A value to set for the property. + /// + /// + /// + /// Set one or more CSS properties for the set of matched elements. + /// A CSS property name. + /// A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old value as arguments. + /// + /// + /// + /// Set one or more CSS properties for the set of matched elements. + /// An object of property-value pairs to set. + /// + /// + }, + 'data': function() { + /// + /// Store arbitrary data associated with the matched elements. + /// A string naming the piece of data to set. + /// The new data value; it can be any Javascript type including Array or Object. + /// + /// + /// + /// Store arbitrary data associated with the matched elements. + /// An object of key-value pairs of data to update. + /// + /// + }, + 'dblclick': function() { + /// + /// Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'delay': function() { + /// + /// Set a timer to delay execution of subsequent items in the queue. + /// An integer indicating the number of milliseconds to delay execution of the next item in the queue. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// + /// + }, + 'delegate': function() { + /// + /// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. + /// A selector to filter the elements that trigger the event. + /// A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names. + /// A function to execute at the time the event is triggered. + /// + /// + /// + /// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. + /// A selector to filter the elements that trigger the event. + /// A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names. + /// An object containing data that will be passed to the event handler. + /// A function to execute at the time the event is triggered. + /// + /// + /// + /// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. + /// A selector to filter the elements that trigger the event. + /// A plain object of one or more event types and functions to execute for them. + /// + /// + }, + 'dequeue': function() { + /// + /// Execute the next function on the queue for the matched elements. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// + /// + }, + 'descendant': function() { + /// + /// Selects all elements that are descendants of a given ancestor. + /// Any valid selector. + /// A selector to filter the descendant elements. + /// + }, + 'detach': function() { + /// + /// Remove the set of matched elements from the DOM. + /// A selector expression that filters the set of matched elements to be removed. + /// + /// + }, + 'die': function() { + /// + /// Remove event handlers previously attached using .live() from the elements. + /// A string containing a JavaScript event type, such as click or keydown. + /// The function that is no longer to be executed. + /// + /// + /// + /// Remove event handlers previously attached using .live() from the elements. + /// A plain object of one or more event types, such as click or keydown and their corresponding functions that are no longer to be executed. + /// + /// + }, + 'disabled': function() { + /// Selects all elements that are disabled. + }, + 'each': function() { + /// + /// Iterate over a jQuery object, executing a function for each matched element. + /// A function to execute for each matched element. + /// + /// + }, + 'element': function() { + /// + /// Selects all elements with the given tag name. + /// An element to search for. Refers to the tagName of DOM nodes. + /// + }, + 'empty': function() { + /// Select all elements that have no children (including text nodes). + }, + 'enabled': function() { + /// Selects all elements that are enabled. + }, + 'end': function() { + /// End the most recent filtering operation in the current chain and return the set of matched elements to its previous state. + /// + }, + 'eq': function() { + /// + /// Select the element at index n within the matched set. + /// Zero-based index of the element to match. + /// + /// + /// Select the element at index n within the matched set. + /// Zero-based index of the element to match, counting backwards from the last element. + /// + }, + 'error': function() { + /// + /// Bind an event handler to the "error" JavaScript event. + /// A function to execute when the event is triggered. + /// + /// + /// + /// Bind an event handler to the "error" JavaScript event. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'even': function() { + /// Selects even elements, zero-indexed. See also odd. + }, + 'fadeIn': function() { + /// + /// Display the matched elements by fading them to opaque. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display the matched elements by fading them to opaque. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Display the matched elements by fading them to opaque. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'fadeOut': function() { + /// + /// Hide the matched elements by fading them to transparent. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Hide the matched elements by fading them to transparent. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Hide the matched elements by fading them to transparent. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'fadeTo': function() { + /// + /// Adjust the opacity of the matched elements. + /// A string or number determining how long the animation will run. + /// A number between 0 and 1 denoting the target opacity. + /// A function to call once the animation is complete. + /// + /// + /// + /// Adjust the opacity of the matched elements. + /// A string or number determining how long the animation will run. + /// A number between 0 and 1 denoting the target opacity. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'fadeToggle': function() { + /// + /// Display or hide the matched elements by animating their opacity. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display or hide the matched elements by animating their opacity. + /// A map of additional options to pass to the method. + /// + /// + }, + 'file': function() { + /// Selects all elements of type file. + }, + 'filter': function() { + /// + /// Reduce the set of matched elements to those that match the selector or pass the function's test. + /// A string containing a selector expression to match the current set of elements against. + /// + /// + /// + /// Reduce the set of matched elements to those that match the selector or pass the function's test. + /// A function used as a test for each element in the set. this is the current DOM element. + /// + /// + /// + /// Reduce the set of matched elements to those that match the selector or pass the function's test. + /// An element to match the current set of elements against. + /// + /// + /// + /// Reduce the set of matched elements to those that match the selector or pass the function's test. + /// An existing jQuery object to match the current set of elements against. + /// + /// + }, + 'find': function() { + /// + /// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element. + /// A jQuery object to match elements against. + /// + /// + /// + /// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element. + /// An element to match elements against. + /// + /// + }, + 'finish': function() { + /// + /// Stop the currently-running animation, remove all queued animations, and complete all animations for the matched elements. + /// The name of the queue in which to stop animations. + /// + /// + }, + 'first': function() { + /// Selects the first matched element. + }, + 'first-child': function() { + /// Selects all elements that are the first child of their parent. + }, + 'first-of-type': function() { + /// Selects all elements that are the first among siblings of the same element name. + }, + 'focus': function() { + /// + /// Bind an event handler to the "focus" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "focus" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'focusin': function() { + /// + /// Bind an event handler to the "focusin" event. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "focusin" event. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'focusout': function() { + /// + /// Bind an event handler to the "focusout" JavaScript event. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "focusout" JavaScript event. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'get': function() { + /// + /// Retrieve the DOM elements matched by the jQuery object. + /// A zero-based integer indicating which element to retrieve. + /// + /// + }, + 'gt': function() { + /// + /// Select all elements at an index greater than index within the matched set. + /// Zero-based index. + /// + }, + 'has': function() { + /// + /// Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element. + /// A DOM element to match elements against. + /// + /// + }, + 'hasClass': function() { + /// + /// Determine whether any of the matched elements are assigned the given class. + /// The class name to search for. + /// + /// + }, + 'header': function() { + /// Selects all elements that are headers, like h1, h2, h3 and so on. + }, + 'height': function() { + /// + /// Set the CSS height of every matched element. + /// An integer representing the number of pixels, or an integer with an optional unit of measure appended (as a string). + /// + /// + /// + /// Set the CSS height of every matched element. + /// A function returning the height to set. Receives the index position of the element in the set and the old height as arguments. Within the function, this refers to the current element in the set. + /// + /// + }, + 'hidden': function() { + /// Selects all elements that are hidden. + }, + 'hide': function() { + /// + /// Hide the matched elements. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Hide the matched elements. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Hide the matched elements. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'hover': function() { + /// + /// Bind two handlers to the matched elements, to be executed when the mouse pointer enters and leaves the elements. + /// A function to execute when the mouse pointer enters the element. + /// A function to execute when the mouse pointer leaves the element. + /// + /// + }, + 'html': function() { + /// + /// Set the HTML contents of each element in the set of matched elements. + /// A string of HTML to set as the content of each matched element. + /// + /// + /// + /// Set the HTML contents of each element in the set of matched elements. + /// A function returning the HTML content to set. Receives the index position of the element in the set and the old HTML value as arguments. jQuery empties the element before calling the function; use the oldhtml argument to reference the previous content. Within the function, this refers to the current element in the set. + /// + /// + }, + 'id': function() { + /// + /// Selects a single element with the given id attribute. + /// An ID to search for, specified via the id attribute of an element. + /// + }, + 'image': function() { + /// Selects all elements of type image. + }, + 'index': function() { + /// + /// Search for a given element from among the matched elements. + /// A selector representing a jQuery collection in which to look for an element. + /// + /// + /// + /// Search for a given element from among the matched elements. + /// The DOM element or first element within the jQuery object to look for. + /// + /// + }, + 'init': function() { + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// A string containing a selector expression + /// A DOM Element, Document, or jQuery to use as context + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// A DOM element to wrap in a jQuery object. + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// An array containing a set of DOM elements to wrap in a jQuery object. + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// A plain object to wrap in a jQuery object. + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// An existing jQuery object to clone. + /// + /// + }, + 'innerHeight': function() { + /// Get the current computed height for the first element in the set of matched elements, including padding but not border. + /// + }, + 'innerWidth': function() { + /// Get the current computed width for the first element in the set of matched elements, including padding but not border. + /// + }, + 'input': function() { + /// Selects all input, textarea, select and button elements. + }, + 'insertAfter': function() { + /// + /// Insert every element in the set of matched elements after the target. + /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted after the element(s) specified by this parameter. + /// + /// + }, + 'insertBefore': function() { + /// + /// Insert every element in the set of matched elements before the target. + /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted before the element(s) specified by this parameter. + /// + /// + }, + 'is': function() { + /// + /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. + /// A function used as a test for the set of elements. It accepts one argument, index, which is the element's index in the jQuery collection.Within the function, this refers to the current DOM element. + /// + /// + /// + /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. + /// An existing jQuery object to match the current set of elements against. + /// + /// + /// + /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. + /// An element to match the current set of elements against. + /// + /// + }, + 'jquery': function() { + /// A string containing the jQuery version number. + /// + }, + 'keydown': function() { + /// + /// Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'keypress': function() { + /// + /// Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'keyup': function() { + /// + /// Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'lang': function() { + /// + /// Selects all elements of the specified language. + /// A language code. + /// + }, + 'last': function() { + /// Selects the last matched element. + }, + 'last-child': function() { + /// Selects all elements that are the last child of their parent. + }, + 'last-of-type': function() { + /// Selects all elements that are the last among siblings of the same element name. + }, + 'length': function() { + /// The number of elements in the jQuery object. + /// + }, + 'live': function() { + /// + /// Attach an event handler for all elements which match the current selector, now and in the future. + /// A string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple, space-separated event types or custom event names. + /// A function to execute at the time the event is triggered. + /// + /// + /// + /// Attach an event handler for all elements which match the current selector, now and in the future. + /// A string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple, space-separated event types or custom event names. + /// An object containing data that will be passed to the event handler. + /// A function to execute at the time the event is triggered. + /// + /// + /// + /// Attach an event handler for all elements which match the current selector, now and in the future. + /// A plain object of one or more JavaScript event types and functions to execute for them. + /// + /// + }, + 'load': function() { + /// + /// Bind an event handler to the "load" JavaScript event. + /// A function to execute when the event is triggered. + /// + /// + /// + /// Bind an event handler to the "load" JavaScript event. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'lt': function() { + /// + /// Select all elements at an index less than index within the matched set. + /// Zero-based index. + /// + }, + 'map': function() { + /// + /// Pass each element in the current matched set through a function, producing a new jQuery object containing the return values. + /// A function object that will be invoked for each element in the current set. + /// + /// + }, + 'mousedown': function() { + /// + /// Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'mouseenter': function() { + /// + /// Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'mouseleave': function() { + /// + /// Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'mousemove': function() { + /// + /// Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'mouseout': function() { + /// + /// Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'mouseover': function() { + /// + /// Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'mouseup': function() { + /// + /// Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'multiple': function() { + /// + /// Selects the combined results of all the specified selectors. + /// Any valid selector. + /// Another valid selector. + /// As many more valid selectors as you like. + /// + }, + 'next': function() { + /// + /// Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'next adjacent': function() { + /// + /// Selects all next elements matching "next" that are immediately preceded by a sibling "prev". + /// Any valid selector. + /// A selector to match the element that is next to the first selector. + /// + }, + 'next siblings': function() { + /// + /// Selects all sibling elements that follow after the "prev" element, have the same parent, and match the filtering "siblings" selector. + /// Any valid selector. + /// A selector to filter elements that are the following siblings of the first selector. + /// + }, + 'nextAll': function() { + /// + /// Get all following siblings of each element in the set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'nextUntil': function() { + /// + /// Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed. + /// A string containing a selector expression to indicate where to stop matching following sibling elements. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed. + /// A DOM node or jQuery object indicating where to stop matching following sibling elements. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'not': function() { + /// + /// Remove elements from the set of matched elements. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Remove elements from the set of matched elements. + /// One or more DOM elements to remove from the matched set. + /// + /// + /// + /// Remove elements from the set of matched elements. + /// A function used as a test for each element in the set. this is the current DOM element. + /// + /// + /// + /// Remove elements from the set of matched elements. + /// An existing jQuery object to match the current set of elements against. + /// + /// + }, + 'nth-child': function() { + /// + /// Selects all elements that are the nth-child of their parent. + /// The index of each child to match, starting with 1, the string even or odd, or an equation ( eg. :nth-child(even), :nth-child(4n) ) + /// + }, + 'nth-last-child': function() { + /// + /// Selects all elements that are the nth-child of their parent, counting from the last element to the first. + /// The index of each child to match, starting with the last one (1), the string even or odd, or an equation ( eg. :nth-last-child(even), :nth-last-child(4n) ) + /// + }, + 'nth-last-of-type': function() { + /// + /// Selects all elements that are the nth-child of their parent, counting from the last element to the first. + /// The index of each child to match, starting with the last one (1), the string even or odd, or an equation ( eg. :nth-last-of-type(even), :nth-last-of-type(4n) ) + /// + }, + 'nth-of-type': function() { + /// + /// Selects all elements that are the nth child of their parent in relation to siblings with the same element name. + /// The index of each child to match, starting with 1, the string even or odd, or an equation ( eg. :nth-of-type(even), :nth-of-type(4n) ) + /// + }, + 'odd': function() { + /// Selects odd elements, zero-indexed. See also even. + }, + 'off': function() { + /// + /// Remove an event handler. + /// One or more space-separated event types and optional namespaces, or just namespaces, such as "click", "keydown.myPlugin", or ".myPlugin". + /// A selector which should match the one originally passed to .on() when attaching event handlers. + /// A handler function previously attached for the event(s), or the special value false. + /// + /// + /// + /// Remove an event handler. + /// An object where the string keys represent one or more space-separated event types and optional namespaces, and the values represent handler functions previously attached for the event(s). + /// A selector which should match the one originally passed to .on() when attaching event handlers. + /// + /// + }, + 'offset': function() { + /// + /// Set the current coordinates of every element in the set of matched elements, relative to the document. + /// An object containing the properties top and left, which are integers indicating the new top and left coordinates for the elements. + /// + /// + /// + /// Set the current coordinates of every element in the set of matched elements, relative to the document. + /// A function to return the coordinates to set. Receives the index of the element in the collection as the first argument and the current coordinates as the second argument. The function should return an object with the new top and left properties. + /// + /// + }, + 'offsetParent': function() { + /// Get the closest ancestor element that is positioned. + /// + }, + 'on': function() { + /// + /// Attach an event handler function for one or more events to the selected elements. + /// One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin". + /// A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element. + /// Data to be passed to the handler in event.data when an event is triggered. + /// A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false. + /// + /// + /// + /// Attach an event handler function for one or more events to the selected elements. + /// An object in which the string keys represent one or more space-separated event types and optional namespaces, and the values represent a handler function to be called for the event(s). + /// A selector string to filter the descendants of the selected elements that will call the handler. If the selector is null or omitted, the handler is always called when it reaches the selected element. + /// Data to be passed to the handler in event.data when an event occurs. + /// + /// + }, + 'one': function() { + /// + /// Attach a handler to an event for the elements. The handler is executed at most once per element. + /// A string containing one or more JavaScript event types, such as "click" or "submit," or custom event names. + /// An object containing data that will be passed to the event handler. + /// A function to execute at the time the event is triggered. + /// + /// + /// + /// Attach a handler to an event for the elements. The handler is executed at most once per element. + /// One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin". + /// A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element. + /// Data to be passed to the handler in event.data when an event is triggered. + /// A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false. + /// + /// + /// + /// Attach a handler to an event for the elements. The handler is executed at most once per element. + /// An object in which the string keys represent one or more space-separated event types and optional namespaces, and the values represent a handler function to be called for the event(s). + /// A selector string to filter the descendants of the selected elements that will call the handler. If the selector is null or omitted, the handler is always called when it reaches the selected element. + /// Data to be passed to the handler in event.data when an event occurs. + /// + /// + }, + 'only-child': function() { + /// Selects all elements that are the only child of their parent. + }, + 'only-of-type': function() { + /// Selects all elements that have no siblings with the same element name. + }, + 'outerHeight': function() { + /// + /// Get the current computed height for the first element in the set of matched elements, including padding, border, and optionally margin. Returns an integer (without "px") representation of the value or null if called on an empty set of elements. + /// A Boolean indicating whether to include the element's margin in the calculation. + /// + /// + }, + 'outerWidth': function() { + /// + /// Get the current computed width for the first element in the set of matched elements, including padding and border. + /// A Boolean indicating whether to include the element's margin in the calculation. + /// + /// + }, + 'parent': function() { + /// + /// Get the parent of each element in the current set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'parents': function() { + /// + /// Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'parentsUntil': function() { + /// + /// Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object. + /// A string containing a selector expression to indicate where to stop matching ancestor elements. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object. + /// A DOM node or jQuery object indicating where to stop matching ancestor elements. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'password': function() { + /// Selects all elements of type password. + }, + 'position': function() { + /// Get the current coordinates of the first element in the set of matched elements, relative to the offset parent. + /// + }, + 'prepend': function() { + /// + /// Insert content, specified by the parameter, to the beginning of each element in the set of matched elements. + /// DOM element, array of elements, HTML string, or jQuery object to insert at the beginning of each element in the set of matched elements. + /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the beginning of each element in the set of matched elements. + /// + /// + /// + /// Insert content, specified by the parameter, to the beginning of each element in the set of matched elements. + /// A function that returns an HTML string, DOM element(s), or jQuery object to insert at the beginning of each element in the set of matched elements. Receives the index position of the element in the set and the old HTML value of the element as arguments. Within the function, this refers to the current element in the set. + /// + /// + }, + 'prependTo': function() { + /// + /// Insert every element in the set of matched elements to the beginning of the target. + /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the beginning of the element(s) specified by this parameter. + /// + /// + }, + 'prev': function() { + /// + /// Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'prevAll': function() { + /// + /// Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'prevUntil': function() { + /// + /// Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object. + /// A string containing a selector expression to indicate where to stop matching preceding sibling elements. + /// A string containing a selector expression to match elements against. + /// + /// + /// + /// Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object. + /// A DOM node or jQuery object indicating where to stop matching preceding sibling elements. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'promise': function() { + /// + /// Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished. + /// The type of queue that needs to be observed. + /// Object onto which the promise methods have to be attached + /// + /// + }, + 'prop': function() { + /// + /// Set one or more properties for the set of matched elements. + /// The name of the property to set. + /// A value to set for the property. + /// + /// + /// + /// Set one or more properties for the set of matched elements. + /// An object of property-value pairs to set. + /// + /// + /// + /// Set one or more properties for the set of matched elements. + /// The name of the property to set. + /// A function returning the value to set. Receives the index position of the element in the set and the old property value as arguments. Within the function, the keyword this refers to the current element. + /// + /// + }, + 'pushStack': function() { + /// + /// Add a collection of DOM elements onto the jQuery stack. + /// An array of elements to push onto the stack and make into a new jQuery object. + /// + /// + /// + /// Add a collection of DOM elements onto the jQuery stack. + /// An array of elements to push onto the stack and make into a new jQuery object. + /// The name of a jQuery method that generated the array of elements. + /// The arguments that were passed in to the jQuery method (for serialization). + /// + /// + }, + 'queue': function() { + /// + /// Manipulate the queue of functions to be executed, once for each matched element. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// An array of functions to replace the current queue contents. + /// + /// + /// + /// Manipulate the queue of functions to be executed, once for each matched element. + /// A string containing the name of the queue. Defaults to fx, the standard effects queue. + /// The new function to add to the queue, with a function to call that will dequeue the next item. + /// + /// + }, + 'radio': function() { + /// Selects all elements of type radio. + }, + 'ready': function() { + /// + /// Specify a function to execute when the DOM is fully loaded. + /// A function to execute after the DOM is ready. + /// + /// + }, + 'remove': function() { + /// + /// Remove the set of matched elements from the DOM. + /// A selector expression that filters the set of matched elements to be removed. + /// + /// + }, + 'removeAttr': function() { + /// + /// Remove an attribute from each element in the set of matched elements. + /// An attribute to remove; as of version 1.7, it can be a space-separated list of attributes. + /// + /// + }, + 'removeClass': function() { + /// + /// Remove a single class, multiple classes, or all classes from each element in the set of matched elements. + /// One or more space-separated classes to be removed from the class attribute of each matched element. + /// + /// + /// + /// Remove a single class, multiple classes, or all classes from each element in the set of matched elements. + /// A function returning one or more space-separated class names to be removed. Receives the index position of the element in the set and the old class value as arguments. + /// + /// + }, + 'removeData': function() { + /// + /// Remove a previously-stored piece of data. + /// A string naming the piece of data to delete. + /// + /// + /// + /// Remove a previously-stored piece of data. + /// An array or space-separated string naming the pieces of data to delete. + /// + /// + }, + 'removeProp': function() { + /// + /// Remove a property for the set of matched elements. + /// The name of the property to remove. + /// + /// + }, + 'replaceAll': function() { + /// + /// Replace each target element with the set of matched elements. + /// A selector expression indicating which element(s) to replace. + /// + /// + }, + 'replaceWith': function() { + /// + /// Replace each element in the set of matched elements with the provided new content and return the set of elements that was removed. + /// The content to insert. May be an HTML string, DOM element, or jQuery object. + /// + /// + /// + /// Replace each element in the set of matched elements with the provided new content and return the set of elements that was removed. + /// A function that returns content with which to replace the set of matched elements. + /// + /// + }, + 'reset': function() { + /// Selects all elements of type reset. + }, + 'resize': function() { + /// + /// Bind an event handler to the "resize" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "resize" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'root': function() { + /// + /// Selects the element that is the root of the document. + /// The index of each child to match, starting with 1, the string even or odd, or an equation ( eg. :nth-last-child(even), :nth-last-child(4n) ) + /// + }, + 'scroll': function() { + /// + /// Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'scrollLeft': function() { + /// + /// Set the current horizontal position of the scroll bar for each of the set of matched elements. + /// An integer indicating the new position to set the scroll bar to. + /// + /// + }, + 'scrollTop': function() { + /// + /// Set the current vertical position of the scroll bar for each of the set of matched elements. + /// An integer indicating the new position to set the scroll bar to. + /// + /// + }, + 'select': function() { + /// + /// Bind an event handler to the "select" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "select" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'selected': function() { + /// Selects all elements that are selected. + }, + 'selector': function() { + /// A selector representing selector originally passed to jQuery(). + /// + }, + 'serialize': function() { + /// Encode a set of form elements as a string for submission. + /// + }, + 'serializeArray': function() { + /// Encode a set of form elements as an array of names and values. + /// + }, + 'show': function() { + /// + /// Display the matched elements. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display the matched elements. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Display the matched elements. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'siblings': function() { + /// + /// Get the siblings of each element in the set of matched elements, optionally filtered by a selector. + /// A string containing a selector expression to match elements against. + /// + /// + }, + 'size': function() { + /// Return the number of elements in the jQuery object. + /// + }, + 'slice': function() { + /// + /// Reduce the set of matched elements to a subset specified by a range of indices. + /// An integer indicating the 0-based position at which the elements begin to be selected. If negative, it indicates an offset from the end of the set. + /// An integer indicating the 0-based position at which the elements stop being selected. If negative, it indicates an offset from the end of the set. If omitted, the range continues until the end of the set. + /// + /// + }, + 'slideDown': function() { + /// + /// Display the matched elements with a sliding motion. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display the matched elements with a sliding motion. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Display the matched elements with a sliding motion. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'slideToggle': function() { + /// + /// Display or hide the matched elements with a sliding motion. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display or hide the matched elements with a sliding motion. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Display or hide the matched elements with a sliding motion. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'slideUp': function() { + /// + /// Hide the matched elements with a sliding motion. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Hide the matched elements with a sliding motion. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Hide the matched elements with a sliding motion. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + }, + 'stop': function() { + /// + /// Stop the currently-running animation on the matched elements. + /// A Boolean indicating whether to remove queued animation as well. Defaults to false. + /// A Boolean indicating whether to complete the current animation immediately. Defaults to false. + /// + /// + /// + /// Stop the currently-running animation on the matched elements. + /// The name of the queue in which to stop animations. + /// A Boolean indicating whether to remove queued animation as well. Defaults to false. + /// A Boolean indicating whether to complete the current animation immediately. Defaults to false. + /// + /// + }, + 'submit': function() { + /// + /// Bind an event handler to the "submit" JavaScript event, or trigger that event on an element. + /// A function to execute each time the event is triggered. + /// + /// + /// + /// Bind an event handler to the "submit" JavaScript event, or trigger that event on an element. + /// An object containing data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'target': function() { + /// Selects the target element indicated by the fragment identifier of the document's URI. + }, + 'text': function() { + /// + /// Set the content of each element in the set of matched elements to the specified text. + /// A string of text to set as the content of each matched element. + /// + /// + /// + /// Set the content of each element in the set of matched elements to the specified text. + /// A function returning the text content to set. Receives the index position of the element in the set and the old text value as arguments. + /// + /// + }, + 'toArray': function() { + /// Retrieve all the DOM elements contained in the jQuery set, as an array. + /// + }, + 'toggle': function() { + /// + /// Display or hide the matched elements. + /// A string or number determining how long the animation will run. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display or hide the matched elements. + /// A map of additional options to pass to the method. + /// + /// + /// + /// Display or hide the matched elements. + /// A string or number determining how long the animation will run. + /// A string indicating which easing function to use for the transition. + /// A function to call once the animation is complete. + /// + /// + /// + /// Display or hide the matched elements. + /// A Boolean indicating whether to show or hide the elements. + /// + /// + }, + 'toggleClass': function() { + /// + /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument. + /// One or more class names (separated by spaces) to be toggled for each element in the matched set. + /// + /// + /// + /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument. + /// One or more class names (separated by spaces) to be toggled for each element in the matched set. + /// A Boolean (not just truthy/falsy) value to determine whether the class should be added or removed. + /// + /// + /// + /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument. + /// A boolean value to determine whether the class should be added or removed. + /// + /// + /// + /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument. + /// A function that returns class names to be toggled in the class attribute of each element in the matched set. Receives the index position of the element in the set, the old class value, and the switch as arguments. + /// A boolean value to determine whether the class should be added or removed. + /// + /// + }, + 'trigger': function() { + /// + /// Execute all handlers and behaviors attached to the matched elements for the given event type. + /// A string containing a JavaScript event type, such as click or submit. + /// Additional parameters to pass along to the event handler. + /// + /// + /// + /// Execute all handlers and behaviors attached to the matched elements for the given event type. + /// A jQuery.Event object. + /// + /// + }, + 'triggerHandler': function() { + /// + /// Execute all handlers attached to an element for an event. + /// A string containing a JavaScript event type, such as click or submit. + /// An array of additional parameters to pass along to the event handler. + /// + /// + }, + 'unbind': function() { + /// + /// Remove a previously-attached event handler from the elements. + /// A string containing a JavaScript event type, such as click or submit. + /// The function that is to be no longer executed. + /// + /// + /// + /// Remove a previously-attached event handler from the elements. + /// A string containing a JavaScript event type, such as click or submit. + /// Unbinds the corresponding 'return false' function that was bound using .bind( eventType, false ). + /// + /// + /// + /// Remove a previously-attached event handler from the elements. + /// A JavaScript event object as passed to an event handler. + /// + /// + }, + 'undelegate': function() { + /// + /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements. + /// A selector which will be used to filter the event results. + /// A string containing a JavaScript event type, such as "click" or "keydown" + /// + /// + /// + /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements. + /// A selector which will be used to filter the event results. + /// A string containing a JavaScript event type, such as "click" or "keydown" + /// A function to execute at the time the event is triggered. + /// + /// + /// + /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements. + /// A selector which will be used to filter the event results. + /// An object of one or more event types and previously bound functions to unbind from them. + /// + /// + /// + /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements. + /// A string containing a namespace to unbind all events from. + /// + /// + }, + 'unload': function() { + /// + /// Bind an event handler to the "unload" JavaScript event. + /// A function to execute when the event is triggered. + /// + /// + /// + /// Bind an event handler to the "unload" JavaScript event. + /// A plain object of data that will be passed to the event handler. + /// A function to execute each time the event is triggered. + /// + /// + }, + 'unwrap': function() { + /// Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place. + /// + }, + 'val': function() { + /// + /// Set the value of each element in the set of matched elements. + /// A string of text or an array of strings corresponding to the value of each matched element to set as selected/checked. + /// + /// + /// + /// Set the value of each element in the set of matched elements. + /// A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old value as arguments. + /// + /// + }, + 'visible': function() { + /// Selects all elements that are visible. + }, + 'width': function() { + /// + /// Set the CSS width of each element in the set of matched elements. + /// An integer representing the number of pixels, or an integer along with an optional unit of measure appended (as a string). + /// + /// + /// + /// Set the CSS width of each element in the set of matched elements. + /// A function returning the width to set. Receives the index position of the element in the set and the old width as arguments. Within the function, this refers to the current element in the set. + /// + /// + }, + 'wrap': function() { + /// + /// Wrap an HTML structure around each element in the set of matched elements. + /// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements. + /// + /// + /// + /// Wrap an HTML structure around each element in the set of matched elements. + /// A callback function returning the HTML content or jQuery object to wrap around the matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set. + /// + /// + }, + 'wrapAll': function() { + /// + /// Wrap an HTML structure around all elements in the set of matched elements. + /// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements. + /// + /// + }, + 'wrapInner': function() { + /// + /// Wrap an HTML structure around the content of each element in the set of matched elements. + /// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the content of the matched elements. + /// + /// + /// + /// Wrap an HTML structure around the content of each element in the set of matched elements. + /// A callback function which generates a structure to wrap around the content of the matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set. + /// + /// + }, +}); + +intellisense.annotate(window, { + '$': function() { + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// A string containing a selector expression + /// A DOM Element, Document, or jQuery to use as context + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// A DOM element to wrap in a jQuery object. + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// An array containing a set of DOM elements to wrap in a jQuery object. + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// A plain object to wrap in a jQuery object. + /// + /// + /// + /// Accepts a string containing a CSS selector which is then used to match a set of elements. + /// An existing jQuery object to clone. + /// + /// + }, +}); + diff --git a/src/ServiceStack.MovieRest/Web/Scripts/jquery-1.10.2.js b/src/ServiceStack.MovieRest/Web/Scripts/jquery-1.10.2.js new file mode 100644 index 00000000..c5c64825 --- /dev/null +++ b/src/ServiceStack.MovieRest/Web/Scripts/jquery-1.10.2.js @@ -0,0 +1,9789 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
    "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
    a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
    "; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
    ", "
    " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + col: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
    ", "
    " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
    " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("