diff --git a/.gitignore b/.gitignore index e80ecc751c2..bcf4fe6f9e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ +#bower deps +**/wwwroot/lib/ bin/ obj/ .idea/ latest/ +node_modules/ /env-vars.bat *.suo #ignore thumbnails created by windows @@ -52,9 +55,6 @@ requestlogs/ *.DS_Store NuGet/ -NuGet.Pcl/ -NuGet.Signed/ -*.pfx build/ @@ -67,3 +67,4 @@ src/ServiceStack/Properties/Resources.resources src/ServiceStack.userprefs *.xap +src/ServiceStack.sln.DotSettings diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index a95a4a6066e..5e9b96594eb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -276,7 +276,7 @@ - [kaza](https://github.com/kaza) - [mishfit](https://github.com/mishfit) - [rfvgyhn](https://github.com/rfvgyhn) (Chris) - - [caiopoiete](https://github.com/caiopoiete) (Caio Proiete) + - [augustoproiete](https://github.com/augustoproiete) (C. Augusto Proiete) - [sjuxax](https://github.com/sjuxax) (Jeff Cook) - [madaleno](https://github.com/madaleno) (Luis Madaleno) - [yavosh](https://github.com/yavosh) (Yavor Shahpasov) @@ -302,6 +302,7 @@ - [barambani](https://github.com/barambani) - [nhalm](https://github.com/et1975) - [scottmcarthur](https://github.com/scottmcarthur) (Scott McArthur) + - [siliconrob](https://github.com/Siliconrob) (Robin Michael) diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 00000000000..8c1ce21b6f6 --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/NuGet.Core/ServiceStack.Client.Core/ServiceStack.Client.Core.nuspec b/NuGet.Core/ServiceStack.Client.Core/ServiceStack.Client.Core.nuspec deleted file mode 100644 index f3db1ecf1fb..00000000000 --- a/NuGet.Core/ServiceStack.Client.Core/ServiceStack.Client.Core.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Client.Core - 1.0.0 - ServiceStack.Client.Core - Service Stack - Service Stack - true - https://servicestack.net/terms - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/img/logo-32.png - JSON, XML, JSV, SOAP and MQ Generic Service Clients. - Opensource .NET and Mono REST Web Services framework - Copyright 2016 Service Stack - en-US - ServiceStack Common Framework Clients ServiceClients Gateway - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Core/ServiceStack.Common.Core/ServiceStack.Common.Core.nuspec b/NuGet.Core/ServiceStack.Common.Core/ServiceStack.Common.Core.nuspec deleted file mode 100644 index 3aa89506ba4..00000000000 --- a/NuGet.Core/ServiceStack.Common.Core/ServiceStack.Common.Core.nuspec +++ /dev/null @@ -1,35 +0,0 @@ - - - - ServiceStack.Common.Core - 1.0.0 - ServiceStack.Common.Core - Service Stack - Service Stack - false - https://servicestack.net/terms - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/img/logo-32.png - Common base library for ServiceStack projects. - Opensource .NET and Mono REST Web Services framework - Copyright 2016 Service Stack - en-US - ServiceStack Common Framework Clients ServiceClients Gateway - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Core/ServiceStack.Interfaces.Core/ServiceStack.Interfaces.Core.nuspec b/NuGet.Core/ServiceStack.Interfaces.Core/ServiceStack.Interfaces.Core.nuspec deleted file mode 100644 index 4110b719ed7..00000000000 --- a/NuGet.Core/ServiceStack.Interfaces.Core/ServiceStack.Interfaces.Core.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - ServiceStack.Interfaces.Core - 1.0.0 - ServiceStack.Interfaces.Core - Service Stack - Service Stack - false - https://servicestack.net/terms - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/img/logo-32.png - Lightweight and implementation-free interfaces for DTO's, providers and adapters. - Opensource .NET and Mono REST Web Services framework - Copyright 2016 Service Stack - en-US - Fast JSON XML CSV HTML SOAP JSV REST Web Service Framework MONO ServiceStack - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Core/nuget.exe b/NuGet.Core/nuget.exe deleted file mode 100755 index 6bb79fe5379..00000000000 Binary files a/NuGet.Core/nuget.exe and /dev/null differ diff --git a/NuGet.Signed/ServiceStack.Api.Swagger.Signed/servicestack.api.swagger.signed.nuspec b/NuGet.Signed/ServiceStack.Api.Swagger.Signed/servicestack.api.swagger.signed.nuspec deleted file mode 100644 index ed91147933e..00000000000 --- a/NuGet.Signed/ServiceStack.Api.Swagger.Signed/servicestack.api.swagger.signed.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Api.Swagger.Signed - ServiceStack.Api.Swagger.Signed - 4.5.0 - Service Stack - Service Stack - ServiceStack integration with Swagger - - Provides a set of services to be discovered by Swagger (http://swagger.wordnik.com/) - Swagger is a specification and complete framework implementation for describing, producing, consuming, and visualizing RESTful web services. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - Swagger API REST Docs ServiceStack - en-US - StackExpress.net 2012 and contributors - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.Authentication.OAuth2.Signed/servicestack.authentication.oauth2.signed.nuspec b/NuGet.Signed/ServiceStack.Authentication.OAuth2.Signed/servicestack.authentication.oauth2.signed.nuspec deleted file mode 100644 index a60f513d7d8..00000000000 --- a/NuGet.Signed/ServiceStack.Authentication.OAuth2.Signed/servicestack.authentication.oauth2.signed.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Authentication.OAuth2.Signed - OAuth2 Providers for ServiceStack - inc. Google, LinkedIn - 4.5.0 - Service Stack - Service Stack - OpenId Auth Providers for ServiceStack - inc. Google, LinkedIn - - Adds OAuth2 Providers for use in ServiceStack Web and REST Services. - Includes built-in support for Google and LinkedIn OAuth2 providers. - - More Info on Auth Providers: - https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - OAuth OAuth2 Google LinkedIn Authentication Auth Provider ServiceStack Web Services - en-US - Copyright 2015 Service Stack - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.Client.Signed/servicestack.client.signed.nuspec b/NuGet.Signed/ServiceStack.Client.Signed/servicestack.client.signed.nuspec deleted file mode 100644 index 87a72a6dc7b..00000000000 --- a/NuGet.Signed/ServiceStack.Client.Signed/servicestack.client.signed.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.Client.Signed - ServiceStack.Client.Signed - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - JSON, XML, JSV, SOAP and MQ Generic Service Clients. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - ServiceStack Common Framework Clients ServiceClients Gateway - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet.Signed/ServiceStack.Common.Signed/servicestack.common.signed.nuspec b/NuGet.Signed/ServiceStack.Common.Signed/servicestack.common.signed.nuspec deleted file mode 100644 index 2030afa435d..00000000000 --- a/NuGet.Signed/ServiceStack.Common.Signed/servicestack.common.signed.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.Common.Signed - ServiceStack.Common.Signed - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Common base library for ServiceStack projects. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Common Framework Clients ServiceClients Gateway - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet.Signed/ServiceStack.Mvc.Signed/servicestack.mvc.signed.nuspec b/NuGet.Signed/ServiceStack.Mvc.Signed/servicestack.mvc.signed.nuspec deleted file mode 100644 index b27aded2c32..00000000000 --- a/NuGet.Signed/ServiceStack.Mvc.Signed/servicestack.mvc.signed.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - ServiceStack.Mvc.Signed - MVC Adapters for integrating with ServiceStack webservices - 4.5.0 - Service Stack - Service Stack - .NET 4.0 project Integration of ServiceStack with MVC3 - - Full details in Mvc PowerPack: http://servicestack.net/mvc-powerpack/ - Adapter classes to provide tight integration and re-usable functionality between ServiceStack and MVC3. - Including adapters for: MiniProfiler, FluentValidation, Funq IOC Controller Factory, Funq Validator Factory - ControllerBase (configured with access to ServiceStack's ICacheClient, ISession, typed UserSession dependencies). - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - MiniProfiler FluentValidation MVC Controller ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.ProtoBuf.Signed/servicestack.protobuf.signed.nuspec b/NuGet.Signed/ServiceStack.ProtoBuf.Signed/servicestack.protobuf.signed.nuspec deleted file mode 100644 index 774b21fdc4f..00000000000 --- a/NuGet.Signed/ServiceStack.ProtoBuf.Signed/servicestack.protobuf.signed.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.ProtoBuf.Signed - Protocol Buffers support for ServiceStack. Includes typed ProtoBuf Client - 4.5.0 - Service Stack - Service Stack - ProtoBuf Format Serializer ContentType ServiceClients for ServiceStack - - Add the ProtoBuf binary format and endpoint to a ServiceStack web service host. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ProtoBuf Fast Binary Serializer Format ContentType REST Web Services ServiceStack - en-US - Copyright 2013 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.Razor.Signed/content/web.config.transform b/NuGet.Signed/ServiceStack.Razor.Signed/content/web.config.transform deleted file mode 100644 index 5632e54d8e1..00000000000 --- a/NuGet.Signed/ServiceStack.Razor.Signed/content/web.config.transform +++ /dev/null @@ -1,35 +0,0 @@ - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.Razor.Signed/servicestack.razor.signed.nuspec b/NuGet.Signed/ServiceStack.Razor.Signed/servicestack.razor.signed.nuspec deleted file mode 100644 index 77396ef6eb2..00000000000 --- a/NuGet.Signed/ServiceStack.Razor.Signed/servicestack.razor.signed.nuspec +++ /dev/null @@ -1,42 +0,0 @@ - - - - ServiceStack.Razor.Signed - ServiceStack.Razor.Signed - 4.5.0 - Service Stack - Service Stack - Provides ServiceStack's HTML Story including integrated support for MVC Razor's ViewEngine - - ServiceStack Razor Documentation: http://razor.servicestack.net - - - Turns ServiceStack into a Complete Web + REST Services Stack. Replaces need for ASP.NET MVC. - - Runs In ASP.NET or Self-host, first-class cross-platform support on .NET / Mono runtimes. - - Add HTML views to existing services. - - Change Views and Layout templates at runtime. - - No Ceremony development options - Pages without controllers, with typed and dynamic View Models. - - Include Partial Markdown views in Razor pages. - - Cascading Layout templates. - - Pretty urls by default (no custom Routes needed). - - Keep all views and assets together. - - Smart View Pages. - - http://razor.servicestack.net - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - Razor ViewEngine View Templates Controllers Mono ASP.NET Self-Host ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.Server.Signed/servicestack.server.signed.nuspec b/NuGet.Signed/ServiceStack.Server.Signed/servicestack.server.signed.nuspec deleted file mode 100644 index 570adad18fc..00000000000 --- a/NuGet.Signed/ServiceStack.Server.Signed/servicestack.server.signed.nuspec +++ /dev/null @@ -1,34 +0,0 @@ - - - - ServiceStack.Server.Signed - ServiceStack.Server.Signed - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Integration libraries and adapters with other major ServiceStack server components. - Includes high-level API's that use OrmLite and Redis including: - AutoQuery, Redis MQ, OrmLiteAuthRepository, OrmLiteCacheClient, OrmLiteAppSettings, - RedisServerEvents and RedisRequestLogger. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - ServiceStack AutoQuery OrmLite Redis MQ Caching ServerEvents - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet.Signed/ServiceStack.Signed/servicestack.signed.nuspec b/NuGet.Signed/ServiceStack.Signed/servicestack.signed.nuspec deleted file mode 100644 index 54084dc3deb..00000000000 --- a/NuGet.Signed/ServiceStack.Signed/servicestack.signed.nuspec +++ /dev/null @@ -1,37 +0,0 @@ - - - - ServiceStack.Signed - ServiceStack.Signed - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Binaries for the ServiceStack web framework. - A simple, fast and cohesive alternative to WCF, MVC and Web API in one - framework for all your services and web apps that's intuitive and Easy-to-use. - - To get started see: servicestack.net/getting-started - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - Fast JSON XML CSV HTML SOAP JSV REST Web Service Framework MONO ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/NuGetPack.cmd b/NuGet/NuGetPack.cmd deleted file mode 100644 index 565594c3646..00000000000 --- a/NuGet/NuGetPack.cmd +++ /dev/null @@ -1,33 +0,0 @@ -SET NUGET=..\src\.nuget\nuget -%NUGET% pack ServiceStack\servicestack.nuspec -symbols -%NUGET% pack ServiceStack.Server\servicestack.server.nuspec -symbols -%NUGET% pack ServiceStack.Interfaces\servicestack.interfaces.nuspec -symbols -%NUGET% pack ServiceStack.Client\servicestack.client.nuspec -symbols -%NUGET% pack ServiceStack.Common\servicestack.common.nuspec -symbols -%NUGET% pack ServiceStack.Mvc\servicestack.mvc.nuspec -symbols -%NUGET% pack ServiceStack.Api.Swagger\servicestack.api.swagger.nuspec -symbols -%NUGET% pack ServiceStack.Razor\servicestack.razor.nuspec -symbols - -%NUGET% pack ServiceStack.Host.AspNet\servicestack.host.aspnet.nuspec -%NUGET% pack ServiceStack.Host.Mvc\servicestack.host.mvc.nuspec - -%NUGET% pack ServiceStack.Authentication.OpenId\servicestack.authentication.openid.nuspec -symbols -%NUGET% pack ServiceStack.Authentication.OAuth2\servicestack.authentication.oauth2.nuspec -symbols - -%NUGET% pack ServiceStack.Authentication.MongoDb\servicestack.authentication.mongodb.nuspec -symbols -%NUGET% pack ServiceStack.Authentication.NHibernate\servicestack.authentication.nhibernate.nuspec -symbols -%NUGET% pack ServiceStack.Authentication.RavenDb\servicestack.authentication.ravendb.nuspec -symbols - -%NUGET% pack ServiceStack.Caching.AwsDynamoDb\servicestack.caching.awsdynamodb.nuspec -symbols -%NUGET% pack ServiceStack.Caching.Azure\servicestack.caching.azure.nuspec -symbols -%NUGET% pack ServiceStack.Caching.Memcached\servicestack.caching.memcached.nuspec -symbols - -%NUGET% pack ServiceStack.Logging.Elmah\servicestack.logging.elmah.nuspec -symbols -%NUGET% pack ServiceStack.Logging.EntLib5\servicestack.logging.entlib5.nuspec -symbols -%NUGET% pack ServiceStack.Logging.EventLog\servicestack.logging.eventlog.nuspec -symbols -%NUGET% pack ServiceStack.Logging.Log4Net\servicestack.logging.log4net.nuspec -symbols -%NUGET% pack ServiceStack.Logging.NLog\servicestack.logging.nlog.nuspec -symbols - -%NUGET% pack ServiceStack.ProtoBuf\servicestack.protobuf.nuspec -symbols -%NUGET% pack ServiceStack.MsgPack\servicestack.msgpack.nuspec -symbols - diff --git a/NuGet/NuGetPush.cmd b/NuGet/NuGetPush.cmd deleted file mode 100644 index eca3f99e164..00000000000 --- a/NuGet/NuGetPush.cmd +++ /dev/null @@ -1,22 +0,0 @@ -SET NUGET=..\src\.nuget\nuget -%NUGET% push ServiceStack.3.9.60.nupkg -%NUGET% push ServiceStack.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Api.Swagger.3.9.60.nupkg -%NUGET% push ServiceStack.Api.Swagger.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Authentication.OAuth2.3.9.60.nupkg -%NUGET% push ServiceStack.Authentication.OAuth2.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Authentication.OpenId.3.9.60.nupkg -%NUGET% push ServiceStack.Authentication.OpenId.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Client.Silverlight.3.9.60.nupkg -%NUGET% push ServiceStack.Common.3.9.60.nupkg -%NUGET% push ServiceStack.Common.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Host.AspNet.3.9.60.nupkg -%NUGET% push ServiceStack.Host.Mvc.3.9.60.nupkg -%NUGET% push ServiceStack.Mvc.3.9.60.nupkg -%NUGET% push ServiceStack.Mvc.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Plugins.MsgPack.3.9.60.nupkg -%NUGET% push ServiceStack.Plugins.MsgPack.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Plugins.ProtoBuf.3.9.60.nupkg -%NUGET% push ServiceStack.Plugins.ProtoBuf.3.9.60.symbols.nupkg -%NUGET% push ServiceStack.Razor.3.9.60.nupkg -%NUGET% push ServiceStack.Razor.3.9.60.symbols.nupkg diff --git a/NuGet/ServiceStack.Api.Swagger/servicestack.api.swagger.nuspec b/NuGet/ServiceStack.Api.Swagger/servicestack.api.swagger.nuspec deleted file mode 100644 index febf48511d1..00000000000 --- a/NuGet/ServiceStack.Api.Swagger/servicestack.api.swagger.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Api.Swagger - ServiceStack additional API for integration with Swagger - 4.5.0 - Service Stack - Service Stack - ServiceStack integration with Swagger - - Provides a set of services to be discovered by Swagger (http://swagger.wordnik.com/) - Swagger is a specification and complete framework implementation for describing, producing, consuming, and visualizing RESTful web services. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - Swagger API REST Docs ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Authentication.MongoDb/servicestack.authentication.mongodb.nuspec b/NuGet/ServiceStack.Authentication.MongoDb/servicestack.authentication.mongodb.nuspec deleted file mode 100644 index 2b5201198f4..00000000000 --- a/NuGet/ServiceStack.Authentication.MongoDb/servicestack.authentication.mongodb.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - ServiceStack.Authentication.MongoDB - 4.5.0 - ServiceStack contributors - ServiceStack contributors - A MongoDB IUserAuthRepository to persist User registration and auth info in a NoSQL Mongo DB - - A MongoDB IUserAuthRepository to persist User registration and auth info in a NoSQL Mongo DB. - Implements ServiceStack's built-in AuthProvider Model: - https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization - inc. Twitter, Facebook, Basic, Digest, Credentials Auth modes out-of-the-box. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Authentication Authorization MongoDB NoSQL POCO Code-First - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Authentication.NHibernate/servicestack.authentication.nhibernate.nuspec b/NuGet/ServiceStack.Authentication.NHibernate/servicestack.authentication.nhibernate.nuspec deleted file mode 100644 index 688b784dbee..00000000000 --- a/NuGet/ServiceStack.Authentication.NHibernate/servicestack.authentication.nhibernate.nuspec +++ /dev/null @@ -1,32 +0,0 @@ - - - - ServiceStack.Authentication.NHibernate - 4.5.0 - ServiceStack contributors - ServiceStack contributors - An NHibernate IUserAuthRepository to persist User registration and auth info in any RDBMS NHibernate supports - - An NHibernate IUserAuthRepository to persist User registration and authentication info in any RDBMS NHibernate supports. - Implements ServiceStack's built-in AuthProvider Model: - https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization - inc. Twitter, Facebook, Basic, Digest, Credentials Auth modes out-of-the-box. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Authentication Authorization NHibernate SQLServer Sqlite Oracle MySql PostgreSQL POCO Code-First - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - diff --git a/NuGet/ServiceStack.Authentication.OAuth2/servicestack.authentication.oauth2.nuspec b/NuGet/ServiceStack.Authentication.OAuth2/servicestack.authentication.oauth2.nuspec deleted file mode 100644 index aa531d059cc..00000000000 --- a/NuGet/ServiceStack.Authentication.OAuth2/servicestack.authentication.oauth2.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Authentication.OAuth2 - OAuth2 Providers for ServiceStack - inc. Google, LinkedIn - 4.5.0 - Service Stack - Service Stack - OpenId Auth Providers for ServiceStack - inc. Google, LinkedIn - - Adds OAuth2 Providers for use in ServiceStack Web and REST Services. - Includes built-in support for Google and LinkedIn OAuth2 providers. - - More Info on Auth Providers: - https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - OAuth OAuth2 Google LinkedIn Authentication Auth Provider ServiceStack Web Services - en-US - Copyright 2016 Service Stack - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Authentication.OpenId/servicestack.authentication.openid.nuspec b/NuGet/ServiceStack.Authentication.OpenId/servicestack.authentication.openid.nuspec deleted file mode 100644 index ed1cba4cebb..00000000000 --- a/NuGet/ServiceStack.Authentication.OpenId/servicestack.authentication.openid.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Authentication.OpenId - OpenId Auth Providers for ServiceStack - inc. Google, Yahoo, MyOpenId - 4.5.0 - Service Stack - Service Stack - OpenId Auth Providers for ServiceStack - inc. Google, Yahoo, MyOpenId - - Adds OpenId Auth Providers for use in ServiceStack Web and REST Services. - Includes built-in support for Google, Yahoo, MyOpenId and Custom OpenId providers. - - More Info on Auth Providers: - https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - OpenId Google Yahoo MyOpenId Authentication Auth Provider ServiceStack REST Web Services ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Authentication.RavenDb/servicestack.authentication.ravendb.nuspec b/NuGet/ServiceStack.Authentication.RavenDb/servicestack.authentication.ravendb.nuspec deleted file mode 100644 index 2c75acb2b9e..00000000000 --- a/NuGet/ServiceStack.Authentication.RavenDb/servicestack.authentication.ravendb.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - ServiceStack.Authentication.RavenDB - 4.5.0 - ServiceStack contributors - ServiceStack contributors - A RavenDB IUserAuthRepository to persist User registration and auth info in a NoSQL Raven DB - - A RavenDB IUserAuthRepository to persist User registration and auth info in a NoSQL Raven DB. - Implements ServiceStack's built-in AuthProvider Model: - https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization - inc. Twitter, Facebook, Basic, Digest, Credentials Auth modes out-of-the-box. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Authentication Authorization RavenDB Raven NoSQL POCO Code-First - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Caching.AwsDynamoDb/servicestack.caching.awsdynamodb.nuspec b/NuGet/ServiceStack.Caching.AwsDynamoDb/servicestack.caching.awsdynamodb.nuspec deleted file mode 100644 index 4b1eb096c9f..00000000000 --- a/NuGet/ServiceStack.Caching.AwsDynamoDb/servicestack.caching.awsdynamodb.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.Caching.AwsDynamoDb - 4.5.0 - ServiceStack contributors - ServiceStack contributors - - Deprecated use new ServiceStack.Aws package. - - An Amazon Web Services In-Memory DynamoDb DataCache implementing ServiceStack's ICacheClient. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Caching AwsDynamoDb Amazon WebServices AWS DynamoDb Cache CacheClient - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Caching.Azure/servicestack.caching.azure.nuspec b/NuGet/ServiceStack.Caching.Azure/servicestack.caching.azure.nuspec deleted file mode 100644 index f76aa35374e..00000000000 --- a/NuGet/ServiceStack.Caching.Azure/servicestack.caching.azure.nuspec +++ /dev/null @@ -1,27 +0,0 @@ - - - - ServiceStack.Caching.Azure - 4.5.0 - Manuel Nelson, ServiceStack contributors - Manuel Nelson, ServiceStack contributors - - An Azure In-Memory DataCache implementing ServiceStack's ICacheClient: - https://github.com/ServiceStack/ServiceStack/wiki/Caching - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Caching Windows Azure Cache CacheClient POCO Code-First - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Caching.Memcached/servicestack.caching.memcached.nuspec b/NuGet/ServiceStack.Caching.Memcached/servicestack.caching.memcached.nuspec deleted file mode 100644 index 8ee12742c4d..00000000000 --- a/NuGet/ServiceStack.Caching.Memcached/servicestack.caching.memcached.nuspec +++ /dev/null @@ -1,27 +0,0 @@ - - - - ServiceStack.Caching.Memcached - 4.5.0 - Service Stack, Thomas Grassauer and ServiceStack contributors - Service Stack, Thomas Grassauer and ServiceStack contributors - - An Memcached cache client implementing ServiceStack's ICacheClient: - https://github.com/ServiceStack/ServiceStack/wiki/Caching - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Caching Memcached Cache CacheClient POCO Code-First - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Client/servicestack.client.nuspec b/NuGet/ServiceStack.Client/servicestack.client.nuspec deleted file mode 100644 index 23715d8255d..00000000000 --- a/NuGet/ServiceStack.Client/servicestack.client.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Client - Service Clients for ServiceStack - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - JSON, XML, JSV, SOAP and MQ Generic Service Clients. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - ServiceStack Common Framework Clients ServiceClients Gateway - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - - - diff --git a/NuGet/ServiceStack.Common/servicestack.common.nuspec b/NuGet/ServiceStack.Common/servicestack.common.nuspec deleted file mode 100644 index fbb8af3114c..00000000000 --- a/NuGet/ServiceStack.Common/servicestack.common.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.Common - Common libs for ServiceStack projects - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Common base library for ServiceStack projects. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ServiceStack Common Framework Clients ServiceClients Gateway - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Gap/build/ServiceStack.Gap.targets b/NuGet/ServiceStack.Gap/build/ServiceStack.Gap.targets deleted file mode 100644 index 799dc3c07d9..00000000000 --- a/NuGet/ServiceStack.Gap/build/ServiceStack.Gap.targets +++ /dev/null @@ -1,25 +0,0 @@ - - - $(CoreCompileDependsOn);RazorGeneratorOutput - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Gap/servicestack.gap.nuspec b/NuGet/ServiceStack.Gap/servicestack.gap.nuspec deleted file mode 100644 index 481222083b6..00000000000 --- a/NuGet/ServiceStack.Gap/servicestack.gap.nuspec +++ /dev/null @@ -1,32 +0,0 @@ - - - - ServiceStack.Gap - ServiceStack.Gap - Tools to help create embedded versions of ServiceStack - 4.0.0 - Service Stack - Service Stack - Tools to help create embedded versions of ServiceStack - - MSBuild Tasks to help creating self-contained embedded versions of ServiceStack that can be ILMerged into a single cross-platform .exe accessed by the users perferred browser or hosted inside a Native Desktop App shell containing a Web Browser widget. - - Once added to a project the install.ps1 script will set the BuildAction to all Razor *.cshtml pages to 'Content' so they get pre-compiled and change all html/img/css assets to Embedded Resources so they get bundled inside the dll. - - This package also includes a copy of ILMerge.exe under \tools that can be used to merge all ServiceStack .dlls into a single exe. See the https://github.com/ServiceStack/ServiceStack.Gap project for more info. - - https://github.com/ServiceStack/ServiceStack.Gap - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - Embed Resources Razor ViewEngine View Templates Mono ASP.NET Self-Host ServiceStack - en-US - Copyright 2013 Service Stack - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Gap/tools/ILMerge License.rtf b/NuGet/ServiceStack.Gap/tools/ILMerge License.rtf deleted file mode 100644 index e8001515e64..00000000000 --- a/NuGet/ServiceStack.Gap/tools/ILMerge License.rtf +++ /dev/null @@ -1,104 +0,0 @@ -{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;} -{\f39\froman\fcharset0\fprq2{\*\panose 02040602050305030304}Book Antiqua;}{\f40\fswiss\fcharset0\fprq2{\*\panose 020b0706030402020204}Franklin Gothic Demi Cond;}{\f41\fswiss\fcharset0\fprq2{\*\panose 020b0503020102020204}Franklin Gothic Book;} -{\f42\froman\fcharset238\fprq2 Times New Roman CE;}{\f43\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f45\froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\froman\fcharset162\fprq2 Times New Roman Tur;} -{\f47\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f48\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f49\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f50\froman\fcharset163\fprq2 Times New Roman (Vietnamese);} -{\f412\fswiss\fcharset238\fprq2 Tahoma CE;}{\f413\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f415\fswiss\fcharset161\fprq2 Tahoma Greek;}{\f416\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f417\fswiss\fcharset177\fprq2 Tahoma (Hebrew);} -{\f418\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f419\fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f420\fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f421\fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f432\froman\fcharset238\fprq2 Book Antiqua CE;} -{\f433\froman\fcharset204\fprq2 Book Antiqua Cyr;}{\f435\froman\fcharset161\fprq2 Book Antiqua Greek;}{\f436\froman\fcharset162\fprq2 Book Antiqua Tur;}{\f439\froman\fcharset186\fprq2 Book Antiqua Baltic;} -{\f442\fswiss\fcharset238\fprq2 Franklin Gothic Demi Cond CE;}{\f443\fswiss\fcharset204\fprq2 Franklin Gothic Demi Cond Cyr;}{\f445\fswiss\fcharset161\fprq2 Franklin Gothic Demi Cond Greek;}{\f446\fswiss\fcharset162\fprq2 Franklin Gothic Demi Cond Tur;} -{\f449\fswiss\fcharset186\fprq2 Franklin Gothic Demi Cond Baltic;}{\f452\fswiss\fcharset238\fprq2 Franklin Gothic Book CE;}{\f453\fswiss\fcharset204\fprq2 Franklin Gothic Book Cyr;}{\f455\fswiss\fcharset161\fprq2 Franklin Gothic Book Greek;} -{\f456\fswiss\fcharset162\fprq2 Franklin Gothic Book Tur;}{\f459\fswiss\fcharset186\fprq2 Franklin Gothic Book Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255; -\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;} -{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\* -\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv -\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\s15\ql \fi-274\li274\ri0\sb120\sl460\slmult0 -\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin274\itap0 \f40\fs44\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \styrsid9786739 1sectionhead;}{\s16\ql \li0\ri0\sb120\sl200\slmult0 -\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \caps\f40\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext16 \styrsid9786739 4laparahead;}{\s17\ql \li0\ri-18\sb120\sl240\slmult0 -\widctlpar\aspalpha\aspnum\faauto\adjustright\rin-18\lin0\itap0 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 \styrsid9786739 2lasubhead;}{\s18\ql \fi-187\li187\ri0\sb60\sl180\slmult0 -\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin187\itap0 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext18 \styrsid9786739 3cnumbered;}{\s19\ql \fi-340\li624\ri0\sb60\sl160\slmult0 -\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin624\itap0 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext19 \styrsid9786739 3inumbered2ndlevel;}{\s20\ql \li0\ri0\sb240\sl240\slmult0 -\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext20 \styrsid9786739 2afrenchsubhead;}{\s21\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 -\cbpat9 \f37\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext21 \ssemihidden \styrsid7154712 Document Map;}}{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\pgptbl {\pgp\ipgp2\itap0\li0\ri0\sb0\sa0\brdrt\brdrs\brdrw20 }{\pgp\ipgp0 -\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid2099452\rsid4207571\rsid5465292\rsid5510097\rsid5510644\rsid7154712\rsid7241305\rsid7672529\rsid7735936\rsid9179139\rsid9786739\rsid10440675\rsid11303133\rsid13130884\rsid14028235\rsid14100361\rsid14113652 -\rsid15276140\rsid16213514}{\*\generator Microsoft Word 11.0.6359;}{\info{\title ILMerge EULA}{\author Ken Leppert}{\operator mbarnett}{\creatim\yr2005\mo3\dy16\hr15\min43}{\revtim\yr2005\mo3\dy16\hr15\min43}{\printim\yr2004\mo4\dy30\hr13\min9}{\version2} -{\edmins0}{\nofpages3}{\nofwords1188}{\nofchars6775}{\*\company Microsoft Corporation}{\nofcharsws7948}{\vern24703}}\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180 -\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1\jexpand\viewkind1\viewscale68\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel -\wrppunct\asianbrkrule\rsidroot9786739\newtblstyruls\nogrowautofit \fet0\sectd \linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang -{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang -{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain -\s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid7154712 \f40\fs44\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f39\fs28\insrsid9786739 MICROSOFT }{ -\b\f39\fs28\insrsid5465292 ILMerge}{\insrsid9786739 -\par }{\b\f39\fs22\insrsid9786739 END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE}{\insrsid9786739 -\par }\pard\plain \s17\qj \li0\ri-17\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin-17\lin0\itap0\pararsid14100361 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f39\insrsid9786739 IMPORTANT\emdash -READ CAREFULLY: }{\f39\insrsid9786739 This End-User License Agreement (\'93EULA\'94) is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation (\'93Microsoft\'94) for th -e Microsoft software that accompanies this EULA, which includes computer software and may include associated media, printed materials, \'93online\'94 or electronic documentation, and Internet-based services (\'93Software\'94).\~ - An amendment or addendum to this EULA may accompany the Software.\~ }{\b\f39\insrsid9786739 -YOU AGREE TO BE BOUND BY THE TERMS OF THIS EULA BY INSTALLING, COPYING, OR OTHERWISE USING THE SOFTWARE. IF YOU DO NOT AGREE, DO NOT INSTALL, COPY, OR USE THE SOFTWARE.}{\insrsid9786739 -\par }\pard\plain \qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1.\~\~\~\~\~\~\~\~ }{ -\b\f39\fs22\insrsid9786739 GRANTS OF LICENSE}{\f39\fs22\insrsid9786739 . Microsoft grants you the rights described in this EULA provided that you comply with all terms and conditions of this EULA.\~ }{\insrsid9786739 -\par }\pard\plain \s19\qj \fi720\li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 1.1\~\~\~\~\~\~ }{ -\b\i\f39\fs22\cf0\insrsid9786739 License Grant}{\f39\fs22\cf0\insrsid9786739 . Microsoft grants to you a personal, nonexclusive, nontransferable, limited license to }{\f39\fs22\insrsid9786739 install and use a reasonable number of copies of -the Software on computers residing on your premises }{\f39\fs22\cf0\insrsid9786739 for the purposes of designing, developing, and testing, your software product(s), provided that you are the only individual using the Software.\~ }{\insrsid9786739 -\par }\pard\plain \s18\qj \fi720\li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1.2\~\~\~\~\~\~ }{ -\b\i\f39\fs22\insrsid9786739 Documentation}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~ }{\f39\fs22\insrsid9786739 You may make and use a reasonabl -e number of copies of any documentation, provided that such copies shall be used only for your personal purposes and are not to be republished or distributed (either in hard copy or electronic form) beyond your premises.}{\insrsid9786739 -\par }\pard \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 {\f39\fs22\insrsid9786739 2.\~\~\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 RESERVATION OF RIGHTS AND OWNERSHIP.\~ }{ -\f39\fs22\insrsid9786739 The Software is licensed as a single product.\~ Its component parts may not be separated. Microsoft reserves all rights not expressly granted to you in this EULA.\~ - The Software is protected by copyright and other intellectual property laws and treaties}{\f39\fs22\insrsid14028235 , and}{\f39\fs22\insrsid9786739 Microsoft }{\f39\fs22\insrsid14028235 (}{\f39\fs22\insrsid9786739 or its suppliers}{ -\f39\fs22\insrsid14028235 , where applicable)}{\f39\fs22\insrsid9786739 own }{\f39\fs22\insrsid14028235 all right, }{\f39\fs22\insrsid9786739 title, }{\f39\fs22\insrsid14028235 and interest in all }{\f39\fs22\insrsid9786739 -intellectual property rights in the Software.\~ }{\b\f39\fs22\insrsid9786739 The Software is licensed, not sold.}{\insrsid9786739 -\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 3.\~\~\~\~\~\~\~\~ }{ -\b\f39\fs22\cf0\insrsid9786739 LIMITATIONS ON REVERSE ENGINEERING, DECOMPILATION, AND DISASSEMBLY}{\b\i\f39\fs22\cf0\insrsid9786739 .}{\f39\fs22\cf0\insrsid9786739 \~ - You may not reverse engineer, decompile, or disassemble the Software, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.}{\insrsid9786739 -\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 4.\~\~\~\~\~\~\~\~ -}{\b\f39\fs22\insrsid9786739 NO RENTAL/COMMERCIAL HOSTING.}{\b\i\f39\fs22\insrsid9786739 }{\f39\fs22\insrsid9786739 You may not rent, lease, lend or provide commercial hosting services with the Software.}{\insrsid9786739 -\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 5.\~\~\~\~\~\~\~\~ }{ -\b\f39\fs22\cf0\insrsid9786739 NO SOFTWARE TRANSFER.\~ }{\f39\fs22\cf0\insrsid9786739 You may not assign or otherwise transfer the SOFTWARE or any of your rights hereunder to any third party.}{\insrsid9786739 -\par }{\f39\fs22\cf0\insrsid9786739 6.\~\~\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 CONSENT TO USE OF DATA.\~ }{\f39\fs22\cf0\insrsid9786739 You - agree that Microsoft and its affiliates may collect and use technical information gathered as part of the product support services provided to you, if any, related to the Software.\~ - Microsoft may use this information solely to improve our products or to provide customized services or technologies to you and will not disclose this information in a form that personally identifies you.\~\~ }{\insrsid9786739 -\par }{\f39\fs22\cf0\insrsid5510644 7}{\f39\fs22\cf0\insrsid9786739 .\~\~\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 ADDITIONAL SOFTWARE/SERVICES.\~ }{\f39\fs22\insrsid9786739 Microsoft is not obligated to provide maintenance, technical supplements}{ -\f39\fs22\insrsid14028235 , updates,}{\f39\fs22\insrsid9786739 or other support to you for the Software licensed under this EULA. }{\f39\fs22\insrsid7241305 }{\f39\fs22\insrsid9786739 In the event that Microsoft does provide such supplements or updates} -{\b\f39\fs22\insrsid9786739 , }{\f39\fs22\insrsid9786739 this EULA applies to such updates, supplements, or add-on components of the Software that Microsoft may provide to -you or make available to you after the date you obtain your initial copy of the Software, unless we provide other terms along with the update, supplement, or add-on component}{\f39\fs22\cf0\insrsid9786739 .\~ - Microsoft reserves the right to discontinue any Internet-based services provided to you or made available to you through the use of the Software.\~ }{\insrsid9786739 -\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid5510644 8}{ -\f39\fs22\insrsid9786739 .\~\~\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 EXPORT RESTRICTIONS}{\f39\fs22\insrsid9786739 .\~ }{\f39\fs22\cgrid0\insrsid9786739 You acknowledge that the Software is subject to U.S. export jurisdiction.\~ - You agree to comply with all applicable international and national laws that apply to the Software, including the U.S. Export Administration Regulations, as well as end-user, end-use, and destination restrictions issued by U.S. and other governments.\~\~ - For additional information see }{\f39\fs22\ul\cgrid0\insrsid9786739 http://www.microsoft.com/exporting/}{\f39\fs22\cgrid0\insrsid9786739 .}{\insrsid9786739 -\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid14113652 9}{ -\f39\fs22\cf0\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 TERMINATION.}{\f39\fs22\cf0\insrsid9786739 \~ Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with }{\f39\fs22\cf0\insrsid7241305 -any }{\f39\fs22\cf0\insrsid9786739 term}{\f39\fs22\cf0\insrsid7241305 or}{\f39\fs22\cf0\insrsid9786739 condition of this EULA. }{\f39\fs22\cf0\insrsid7241305 }{\f39\fs22\cf0\insrsid9786739 -In such event, you must destroy all copies of the Software and all of its component parts.}{\insrsid9786739 -\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1}{ -\f39\fs22\insrsid14113652 0}{\f39\fs22\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 DISCLAIMER OF WARRANTIES}{\b\f39\fs22\insrsid9786739 .\~ - TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND ITS SUPPLIERS PROVIDE THE SOFTWARE}{\f39\fs22\insrsid9786739 }{\b\f39\fs22\insrsid9786739 AND SUPPORT SERVICES (IF ANY) }{\b\i\f39\fs22\insrsid9786739 AS IS AND WITH ALL FAULTS}{ -\b\f39\fs22\insrsid9786739 , AND HEREBY DISCLAIM ALL OTHER WARRANTIES AND CONDITIONS, WHETHER EXPRESS, IMPLIED - OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF RELIABILITY OR AVAILABILITY, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF WORKMANLI -K -E EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE, ALL WITH REGARD TO THE SOFTWARE, AND THE PROVISION OF OR FAILURE TO PROVIDE SUPPORT OR OTHER SERVICES, INFORMATION, SOFTWARE, AND RELATED CONTENT THROUGH THE SOFTWARE OR OTHERWISE ARISING OUT OF THE - USE OF THE SOFTWARE.\~ ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT WITH REGARD TO THE SOFTWARE.}{\insrsid9786739 -\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 1}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 EXCLUSION OF INCIDENTAL, CONSEQUENTIAL AND CERTAIN OTHER DAMAGES}{\b\f39\fs22\insrsid9786739 .\~ - }{\b\caps\f39\fs22\insrsid9786739 -To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any special, incidental, punitive, indirect, or consequential damages whatsoever (including, but not limited to, damages for loss of profit -s, LOSS OF DATA, or confidential or other information}{\b\f39\fs22\insrsid9786739 , }{\b\caps\f39\fs22\insrsid9786739 -for business interruption, for personal injury, for loss of privacy, for failure to meet any duty including of good faith or of reasonable care, for negligence, and}{\b\f39\fs22\insrsid9786739 }{\b\caps\f39\fs22\insrsid9786739 -for any other pecuniary or other los -s whatsoever) arising out of or in any way related to the use of or inability to use the SOFTWARE, the provision of or failure to provide Support OR OTHER Services, informatIon, software, and related CONTENT through the software or otherwise arising out o -f - the use of the software, or otherwise under or in connection with any provision of this EULA, even in the event of the fault, tort (including negligence), misrepresentation, strict liability, breach of contract or breach of warranty of Microsoft or any s -upplier, and even if Microsoft or any supplier has been advised of the possibility of such damages. }{\insrsid9786739 -\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 2}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 LIMITATION OF LIABILITY AND REMEDIES}{\b\f39\fs22\insrsid9786739 -. NOTWITHSTANDING ANY DAMAGES THAT YOU MIGHT INCUR FOR ANY REASON WHATSOEVER (INCLUDING, WITHOUT LIMITATION, A -LL DAMAGES REFERENCED HEREIN AND ALL DIRECT OR GENERAL DAMAGES IN CONTRACT OR ANYTHING ELSE), THE ENTIRE LIABILITY OF MICROSOFT AND ANY OF ITS SUPPLIERS UNDER ANY PROVISION OF THIS EULA AND YOUR EXCLUSIVE REMEDY HEREUNDER SHALL BE LIMITED TO THE GREATER O -F THE ACTUAL DAMAGES YOU INCUR IN REASONABLE RELIANCE ON THE SOFTWARE UP TO THE AMOUNT ACTUALLY PAID BY YOU FOR THE SOFTWARE}{\f39\fs22\insrsid9786739 }{\b\f39\fs22\insrsid9786739 OR US$5.00.\~ - THE FOREGOING LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, EVEN IF ANY REMEDY FAILS ITS ESSENTIAL PURPOSE.}{\insrsid9786739 -\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 3}{\f39\fs22\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 APPLICABLE LAW.\~ }{\f39\fs22\insrsid7735936 T}{\f39\fs22\insrsid9786739 his EULA }{\f39\fs22\insrsid7735936 -shall be construed under and }{\f39\fs22\insrsid9786739 governed by the laws of the State of Washington}{\f39\fs22\insrsid7735936 , without regard to conflicts of law principles}{\f39\fs22\insrsid9786739 .\~ }{\insrsid9786739 -\par }\pard\plain \s20\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl240\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\insrsid9786739 1}{\f39\insrsid14113652 -4}{\f39\insrsid9786739 .\~\~\~\~ }{\b\f39\insrsid9786739 ENTIRE AGREEMENT; SEVERABILITY.\~ }{\f39\insrsid9786739 This -EULA (including any addendum or amendment to this EULA which is included with the Software) are the entire agreement between you and Microsoft relating to the Software and the support services (if any) and they supersede all prior or contemporaneous oral -or written communications,\~proposals and representations with respect to the Software or any other subject matter covered by this EULA.\~ - If any provision of this EULA is held to be void, invalid, unenforceable or illegal, the other provisions shall continue in full force and effect}{\insrsid9786739 -\par }\pard\plain \qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\insrsid10440675 -\par }} \ No newline at end of file diff --git a/NuGet/ServiceStack.Gap/tools/ILMerge.exe b/NuGet/ServiceStack.Gap/tools/ILMerge.exe deleted file mode 100644 index 9667425b396..00000000000 Binary files a/NuGet/ServiceStack.Gap/tools/ILMerge.exe and /dev/null differ diff --git a/NuGet/ServiceStack.Gap/tools/install.ps1 b/NuGet/ServiceStack.Gap/tools/install.ps1 deleted file mode 100644 index 401c3fd39b5..00000000000 --- a/NuGet/ServiceStack.Gap/tools/install.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -param($installPath, $toolsPath, $package, $project) - -# Set BuildAction of Razor Views to Content -function CompileRazorViews($projectItems) { - $projectItems | %{ - $x = $_.Name.ToLower() - if ($x -like "*.cshtml") { - $_.Properties.Item("BuildAction").Value = [int]2 # Content - } - - # Recursively - if ($_.ProjectItems) { - CompileRazorViews $_.ProjectItems - } - } -} - -# Embed Resource Files -function EmbedResources($projectItems) { - $projectItems | %{ - $ext = [System.IO.Path]::GetExtension($_.Name.ToLower()) - $embedExts = ".js",".css",".md",".html",".htm",".png",".gif",".jpg",".jpeg",".bmp",".ico",".svg",".tiff",".webp",".webm",".xap",".xaml",".flv",".swf",".xml",".csv",".pdf",".mp3",".wav",".mpg",".ttf",".woff",".eot",".map" - - if ($embedExts -contains $ext) { - $_.Properties.Item("BuildAction").Value = [int]3 # Embed - } - - # Recursively - if ($_.ProjectItems) { - EmbedResources $_.ProjectItems - } - } -} - -CompileRazorViews $project.ProjectItems -EmbedResources $project.ProjectItems - diff --git a/NuGet/ServiceStack.Gap/tools/uninstall.ps1 b/NuGet/ServiceStack.Gap/tools/uninstall.ps1 deleted file mode 100644 index 750d3ccbfc0..00000000000 --- a/NuGet/ServiceStack.Gap/tools/uninstall.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -param($installPath, $toolsPath, $package, $project) - -<# -$targetsFileName = 'ServiceStack.Razor.BuildTask.targets'; - -# Need to load MSBuild assembly if it's not loaded yet. -Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' - -# Grab the loaded MSBuild project for the project -$msbuild = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName) | Select-Object -First 1 - -# Remove imports to .targets -$msbuild.Xml.Imports | Where-Object {$_.Project.ToLowerInvariant().EndsWith($targetsFileName.ToLowerInvariant()) } | Foreach { - $_.Parent.RemoveChild( $_ ) - [string]::Format( "Removed import of '{0}'" , $_.Project ) -} -#> \ No newline at end of file diff --git a/NuGet/ServiceStack.Host.AspNet/content/App_Start/AppHost.cs.pp b/NuGet/ServiceStack.Host.AspNet/content/App_Start/AppHost.cs.pp deleted file mode 100644 index 078740d9cde..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/App_Start/AppHost.cs.pp +++ /dev/null @@ -1,79 +0,0 @@ -using System.Configuration; -using ServiceStack; -using ServiceStack.Auth; -using ServiceStack.Configuration; -using ServiceStack.Data; -using ServiceStack.OrmLite; - -[assembly: WebActivator.PreApplicationStartMethod(typeof($rootnamespace$.App_Start.AppHost), "Start")] - - -/** - * Entire ServiceStack Starter Template configured with a 'Hello' Web Service and a 'Todo' Rest Service. - * - * Auto-Generated Metadata API page at: /metadata - * See other complete web service examples at: https://github.com/ServiceStack/ServiceStack.Examples - */ - -namespace $rootnamespace$.App_Start -{ - public class AppHost : AppHostBase - { - public AppHost() //Tell ServiceStack the name and where to find your web services - : base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly) { } - - public override void Configure(Funq.Container container) - { - //Set JSON web services to return idiomatic JSON camelCase properties - ServiceStack.Text.JsConfig.EmitCamelCaseNames = true; - - //Configure User Defined REST Paths - Routes - .Add("/hello") - .Add("/hello/{Name*}"); - - //Uncomment to change the default ServiceStack configuration - //SetConfig(new HostConfig { - //}); - - //Enable Authentication - //ConfigureAuth(container); - - //Register all your dependencies - container.Register(new TodoRepository()); - } - - /* Example ServiceStack Authentication and CustomUserSession */ - private void ConfigureAuth(Funq.Container container) - { - var appSettings = new AppSettings(); - - //Default route: /auth/{provider} - Plugins.Add(new AuthFeature(() => new CustomUserSession(), - new IAuthProvider[] { - new CredentialsAuthProvider(appSettings), - new FacebookAuthProvider(appSettings), - new TwitterAuthProvider(appSettings), - new BasicAuthProvider(appSettings), - })); - - //Default route: /register - Plugins.Add(new RegistrationFeature()); - - //Requires ConnectionString configured in Web.Config - var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString; - container.Register(c => - new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider)); - - container.Register(c => - new OrmLiteAuthRepository(c.Resolve())); - - container.Resolve().InitSchema(); - } - - public static void Start() - { - new AppHost().Init(); - } - } -} diff --git a/NuGet/ServiceStack.Host.AspNet/content/App_Start/PageBase.cs.pp b/NuGet/ServiceStack.Host.AspNet/content/App_Start/PageBase.cs.pp deleted file mode 100644 index 446f4be9a2c..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/App_Start/PageBase.cs.pp +++ /dev/null @@ -1,66 +0,0 @@ -using System.Web.UI; -using ServiceStack; -using ServiceStack.Caching; - - -/** - * Base ASP.NET WebForms page using ServiceStack's Compontents, see: http://www.servicestack.net/mvc-powerpack/ - */ - -namespace $rootnamespace$.App_Start -{ - //A customizeable typed UserSession that can be extended with your own properties - public class CustomUserSession : AuthUserSession - { - public string CustomProperty { get; set; } - } - - public class PageBase : Page - { - /// - /// Typed UserSession - /// - private object userSession; - protected virtual TUserSession SessionAs() - { - return (TUserSession)(userSession ?? (userSession = Cache.SessionAs())); - } - - protected CustomUserSession UserSession - { - get - { - return SessionAs(); - } - } - - public new ICacheClient Cache - { - get { return HostContext.Resolve(); } - } - - private ISessionFactory sessionFactory; - public virtual ISessionFactory SessionFactory - { - get { return sessionFactory ?? (sessionFactory = HostContext.Resolve()) ?? new SessionFactory(Cache); } - } - - /// - /// Dynamic SessionBag Bag - /// - private ISession sessionBag; - public new ISession SessionBag - { - get - { - return sessionBag ?? (sessionBag = SessionFactory.GetOrCreateSession()); - } - } - - public void ClearSession() - { - userSession = null; - this.Cache.Remove(SessionFeature.GetSessionKey()); - } - } -} diff --git a/NuGet/ServiceStack.Host.AspNet/content/App_Start/WebServiceExamples.cs.pp b/NuGet/ServiceStack.Host.AspNet/content/App_Start/WebServiceExamples.cs.pp deleted file mode 100644 index b997f3b88c1..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/App_Start/WebServiceExamples.cs.pp +++ /dev/null @@ -1,133 +0,0 @@ -using System.Linq; -using System.Collections.Generic; -using ServiceStack; - -namespace $rootnamespace$ -{ - //Request DTO - public class Hello - { - public string Name { get; set; } - } - - //Response DTO - public class HelloResponse - { - public string Result { get; set; } - public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized - } - - //Can be called via any endpoint or format, see: http://mono.servicestack.net/ServiceStack.Hello/ - public class HelloService : Service - { - public object Any(Hello request) - { - return new HelloResponse { Result = "Hello, " + request.Name }; - } - } - - //REST Resource DTO - [Route("/todos")] - [Route("/todos/{Ids}")] - public class Todos : IReturn> - { - public long[] Ids { get; set; } - public Todos(params long[] ids) - { - this.Ids = ids; - } - } - - [Route("/todos", "POST")] - [Route("/todos/{Id}", "PUT")] - public class Todo : IReturn - { - public long Id { get; set; } - public string Content { get; set; } - public int Order { get; set; } - public bool Done { get; set; } - } - - public class TodosService : Service - { - public TodoRepository Repository { get; set; } //Injected by IOC - - public object Get(Todos request) - { - return request.Ids.IsEmpty() - ? Repository.GetAll() - : Repository.GetByIds(request.Ids); - } - - public object Post(Todo todo) - { - return Repository.Store(todo); - } - - public object Put(Todo todo) - { - return Repository.Store(todo); - } - - public void Delete(Todos request) - { - Repository.DeleteByIds(request.Ids); - } - } - - public class TodoRepository - { - List todos = new List(); - - public List GetByIds(long[] ids) - { - return todos.Where(x => ids.Contains(x.Id)).ToList(); - } - - public List GetAll() - { - return todos; - } - - public Todo Store(Todo todo) - { - var existing = todos.FirstOrDefault(x => x.Id == todo.Id); - if (existing == null) - { - var newId = todos.Count > 0 ? todos.Max(x => x.Id) + 1 : 1; - todo.Id = newId; - todos.Add(todo); - } - else - { - existing.PopulateWith(todo); - } - return todo; - } - - public void DeleteByIds(params long[] ids) - { - todos.RemoveAll(x => ids.Contains(x.Id)); - } - } - - -/* Example calling above Service with ServiceStack's C# clients: - - var client = new JsonServiceClient(BaseUri); - List all = client.Get(new Todos()); // Count = 0 - - var todo = client.Post( - new Todo { Content = "New TODO", Order = 1 }); // todo.Id = 1 - all = client.Get(new Todos()); // Count = 1 - - todo.Content = "Updated TODO"; - todo = client.Put(todo); // todo.Content = Updated TODO - - client.Delete(new Todos(todo.Id)); - all = client.Get(new Todos()); // Count = 0 - -*/ - -} - diff --git a/NuGet/ServiceStack.Host.AspNet/content/README.txt b/NuGet/ServiceStack.Host.AspNet/content/README.txt deleted file mode 100644 index a75aa9feab6..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/README.txt +++ /dev/null @@ -1,36 +0,0 @@ -To enable the Mini Profiler add the following lines in to Global class in Global.asax.cs: - - - protected void Application_BeginRequest(object src, EventArgs e) - { - if (Request.IsLocal) - ServiceStack.MiniProfiler.Profiler.Start(); - } - - protected void Application_EndRequest(object src, EventArgs e) - { - ServiceStack.MiniProfiler.Profiler.Stop(); - } - - -For more info on the MiniProfiler see v3.09 of the https://github.com/ServiceStack/ServiceStack/wiki/Release-Notes - - -The Urls for metadata page and included Services: - - * /metadata - Auto generated metadata pages - * /hello - Simple Hello World Service. see: http://www.servicestack.net/ServiceStack.Hello/ - * /todos - Simple REST Service. see: http://www.servicestack.net/Backbone.Todos/ - - * /default.htm - Backbone.js TODO application talking to the TODO REST service at /todos - - -For more info about ServiceStack please visit: http://www.servicestack.net - -Feel free to ask questions about ServiceStack on: -http://stackoverflow.com/ - -or on the mailing Group at: -http://groups.google.com/group/servicestack - -Enjoy! \ No newline at end of file diff --git a/NuGet/ServiceStack.Host.AspNet/content/default.htm b/NuGet/ServiceStack.Host.AspNet/content/default.htm deleted file mode 100644 index 78c2a89314c..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/default.htm +++ /dev/null @@ -1,685 +0,0 @@ - - - - - Backbone Demo: Todos - - - - - - - - - - - - -
- -
-

Todos

-
- -
- -
- - -
- -
-
    -
    - -
    - -
    - -
    - - - -
    - Created by -
    - Jérôme Gravel-Niquet -
    -
    - Powered By Open Source -
    - servicestack.net - | redis - | mono -
    - - - - - - - - - - - - - - diff --git a/NuGet/ServiceStack.Host.AspNet/content/jqunback-1.51.min.js b/NuGet/ServiceStack.Host.AspNet/content/jqunback-1.51.min.js deleted file mode 100644 index 97da2a076f8..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/jqunback-1.51.min.js +++ /dev/null @@ -1,68 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function(a,b){function cg(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cd(a){if(!bZ[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bZ[a]=c}return bZ[a]}function cc(a,b){var c={};d.each(cb.concat.apply([],cb.slice(0,b)),function(){c[this]=a});return c}function bY(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bX(){try{return new a.XMLHttpRequest}catch(b){}}function bW(){d(a).unload(function(){for(var a in bU)bU[a](0,1)})}function bQ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(r,"`").replace(s,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,q=[],r=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function w(){return!0}function v(){return!1}function g(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.1",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1){var f=E.call(arguments,0),g=b,h=function(a){return function(b){f[a]=arguments.length>1?E.call(arguments,0):b,--g||c.resolveWith(e,f)}};while(b--)a=f[b],a&&d.isFunction(a.promise)?a.promise().then(h(b),c.reject):--g;g||c.resolveWith(e,f)}else c!==a&&c.resolve(a);return e},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="
    a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e),b=e=f=null}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
    ",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
    t
    ";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!g(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,h=b.nodeType,i=h?d.cache:b,j=h?b[d.expando]:d.expando;if(!i[j])return;if(c){var k=e?i[j][f]:i[j];if(k){delete k[c];if(!g(k))return}}if(e){delete i[j][f];if(!g(i[j]))return}var l=i[j][f];d.support.deleteExpando||i!=a?delete i[j]:i[j]=null,l?(i[j]={},h||(i[j].toJSON=d.noop),i[j][f]=l):h&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var k=i?f:0,l=i?f+1:h.length;k=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=k.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&l.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:m.test(a.nodeName)||n.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var p=/\.(.*)$/,q=/^(?:textarea|input|select)$/i,r=/\./g,s=/ /g,t=/[^\w\s.|`]/g,u=function(a){return a.replace(t,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=v;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),u).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(p,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(q.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return q.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return q.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.getAttribute("type")},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(d||!l.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return k(c,null,null,[a]).length>0})}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div
    ","
    "]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){$(a,e),f=_(a),g=_(e);for(h=0;f[h];++h)$(f[h],g[h])}if(b){Z(a,e);if(c){f=_(a),g=_(e);for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/)<[^<]*)*<\/script>/gi,bA=/^(?:select|textarea)/i,bB=/\s+/,bC=/([?&])_=[^&]*/,bD=/(^|\-)([a-z])/g,bE=function(a,b,c){return b+c.toUpperCase()},bF=/^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/,bG=d.fn.load,bH={},bI={},bJ,bK;try{bJ=c.location.href}catch(bL){bJ=c.createElement("a"),bJ.href="",bJ=bJ.href}bK=bF.exec(bJ.toLowerCase()),d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bG)return bG.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
    ").append(c.replace(bz,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bA.test(this.nodeName)||bu.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(br,"\r\n")}}):{name:b.name,value:c.replace(br,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bJ,isLocal:bv.test(bK[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bM(bH),ajaxTransport:bM(bI),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bP(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bQ(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bD,bE)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bt.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bs,"").replace(bx,bK[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bB),e.crossDomain||(q=bF.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bK[1]||q[2]!=bK[2]||(q[3]||(q[1]==="http:"?80:443))!=(bK[3]||(bK[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bN(bH,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!bw.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(by.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bC,"$1_="+w);e.url=x+(x===e.url?(by.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bN(bI,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bO(g,a[g],c,f);return e.join("&").replace(bp,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bR=d.now(),bS=/(\=)\?(&|$)|()\?\?()/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bR++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bS.test(b.url)||f&&bS.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bS,l),b.url===j&&(f&&(k=k.replace(bS,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bT=d.now(),bU,bV;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bX()||bY()}:bX,bV=d.ajaxSettings.xhr(),d.support.ajax=!!bV,d.support.cors=bV&&"withCredentials"in bV,bV=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),(!a.crossDomain||a.hasContent)&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bU[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bU||(bU={},bW()),h=bT++,g.onreadystatechange=bU[h]=c):c()},abort:function(){c&&c(0,1)}}}});var bZ={},b$=/^(?:toggle|show|hide)$/,b_=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,ca,cb=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(cc("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:cc("show",1),slideUp:cc("hide",1),slideToggle:cc("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!ca&&(ca=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
    ";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=cf.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!cf.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=cg(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=cg(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window);// Underscore.js 1.1.5 -// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore -(function(){var q=this,D=q._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,E=k.unshift,F=o.toString,m=o.hasOwnProperty,s=k.forEach,t=k.map,u=k.reduce,v=k.reduceRight,w=k.filter,x=k.every,y=k.some,p=k.indexOf,z=k.lastIndexOf;o=Array.isArray;var G=Object.keys,A=Function.prototype.bind,c=function(a){return new l(a)};if(typeof module!=="undefined"&&module.exports){module.exports=c;c._=c}else q._=c;c.VERSION="1.1.5";var j=c.each=c.forEach=function(a,b,d){if(a!=null)if(s&&a.forEach===s)a.forEach(b, -d);else if(c.isNumber(a.length))for(var e=0,f=a.length;e=e.computed&&(e={value:f,computed:g})});return e.value};c.min=function(a,b,d){if(!b&&c.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};j(a,function(f,g,h){g=b?b.call(d,f,g,h):f;gh?1:0}),"value")};c.sortedIndex= -function(a,b,d){d=d||c.identity;for(var e=0,f=a.length;e>1;d(a[g])=0})})};c.zip=function(){for(var a=i.call(arguments),b=c.max(c.pluck(a,"length")),d=Array(b),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};c.keys=G||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)if(m.call(a, -d))b[b.length]=d;return b};c.values=function(a){return c.map(a,c.identity)};c.functions=c.methods=function(a){return c.filter(c.keys(a),function(b){return c.isFunction(a[b])}).sort()};c.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};c.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)if(a[d]==null)a[d]=b[d]});return a};c.clone=function(a){return c.isArray(a)?a.slice():c.extend({},a)};c.tap=function(a,b){b(a);return a};c.isEqual=function(a, -b){if(a===b)return true;var d=typeof a;if(d!=typeof b)return false;if(a==b)return true;if(!a&&b||a&&!b)return false;if(a._chain)a=a._wrapped;if(b._chain)b=b._wrapped;if(a.isEqual)return a.isEqual(b);if(c.isDate(a)&&c.isDate(b))return a.getTime()===b.getTime();if(c.isNaN(a)&&c.isNaN(b))return false;if(c.isRegExp(a)&&c.isRegExp(b))return a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline;if(d!=="object")return false;if(a.length&&a.length!==b.length)return false; -d=c.keys(a);var e=c.keys(b);if(d.length!=e.length)return false;for(var f in a)if(!(f in b)||!c.isEqual(a[f],b[f]))return false;return true};c.isEmpty=function(a){if(c.isArray(a)||c.isString(a))return a.length===0;for(var b in a)if(m.call(a,b))return false;return true};c.isElement=function(a){return!!(a&&a.nodeType==1)};c.isArray=o||function(a){return F.call(a)==="[object Array]"};c.isArguments=function(a){return!!(a&&m.call(a,"callee"))};c.isFunction=function(a){return!!(a&&a.constructor&&a.call&& -a.apply)};c.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};c.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};c.isNaN=function(a){return a!==a};c.isBoolean=function(a){return a===true||a===false};c.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};c.isRegExp=function(a){return!!(a&&a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};c.isNull=function(a){return a===null};c.isUndefined=function(a){return a===void 0};c.noConflict=function(){q._= -D;return this};c.identity=function(a){return a};c.times=function(a,b,d){for(var e=0;e/g,interpolate:/<%=([\s\S]+?)%>/g};c.template=function(a,b){var d=c.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate, -function(e,f){return"',"+f.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(e,f){return"');"+f.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return b?d(b):d};var l=function(a){this._wrapped=a};c.prototype=l.prototype;var r=function(a,b){return b?c(a).chain():a},I=function(a,b){l.prototype[a]=function(){var d=i.call(arguments);E.call(d,this._wrapped);return r(b.apply(c, -d),this._chain)}};c.mixin(c);j(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=k[a];l.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];l.prototype[a]=function(){return r(b.apply(this._wrapped,arguments),this._chain)}});l.prototype.chain=function(){this._chain=true;return this};l.prototype.value=function(){return this._wrapped}})(); -// Backbone.js 0.3.3 -// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc. -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://documentcloud.github.com/backbone -(function(){var e;e=typeof exports!=="undefined"?exports:this.Backbone={};e.VERSION="0.3.3";var f=this._;if(!f&&typeof require!=="undefined")f=require("underscore")._;var h=this.jQuery||this.Zepto;e.emulateHTTP=false;e.emulateJSON=false;e.Events={bind:function(a,b){this._callbacks||(this._callbacks={});(this._callbacks[a]||(this._callbacks[a]=[])).push(b);return this},unbind:function(a,b){var c;if(a){if(c=this._callbacks)if(b){c=c[a];if(!c)return this;for(var d=0,g=c.length;d/g,">").replace(/"/g, -""")},set:function(a,b){b||(b={});if(!a)return this;if(a.attributes)a=a.attributes;var c=this.attributes,d=this._escapedAttributes;if(!b.silent&&this.validate&&!this._performValidation(a,b))return false;if("id"in a)this.id=a.id;for(var g in a){var i=a[g];if(!f.isEqual(c[g],i)){c[g]=i;delete d[g];if(!b.silent){this._changed=true;this.trigger("change:"+g,this,i,b)}}}!b.silent&&this._changed&&this.change(b);return this},unset:function(a,b){b||(b={});var c={};c[a]=void 0;if(!b.silent&&this.validate&& -!this._performValidation(c,b))return false;delete this.attributes[a];delete this._escapedAttributes[a];if(!b.silent){this._changed=true;this.trigger("change:"+a,this,void 0,b);this.change(b)}return this},clear:function(a){a||(a={});var b=this.attributes,c={};for(attr in b)c[attr]=void 0;if(!a.silent&&this.validate&&!this._performValidation(c,a))return false;this.attributes={};this._escapedAttributes={};if(!a.silent){this._changed=true;for(attr in b)this.trigger("change:"+attr,this,void 0,a);this.change(a)}return this}, -fetch:function(a){a||(a={});var b=this,c=j(a.error,b,a);(this.sync||e.sync)("read",this,function(d){if(!b.set(b.parse(d),a))return false;a.success&&a.success(b,d)},c);return this},save:function(a,b){b||(b={});if(a&&!this.set(a,b))return false;var c=this,d=j(b.error,c,b),g=this.isNew()?"create":"update";(this.sync||e.sync)(g,this,function(i){if(!c.set(c.parse(i),b))return false;b.success&&b.success(c,i)},d);return this},destroy:function(a){a||(a={});var b=this,c=j(a.error,b,a);(this.sync||e.sync)("delete", -this,function(d){b.collection&&b.collection.remove(b);a.success&&a.success(b,d)},c);return this},url:function(){var a=k(this.collection);if(this.isNew())return a;return a+(a.charAt(a.length-1)=="/"?"":"/")+this.id},parse:function(a){return a},clone:function(){return new this.constructor(this)},isNew:function(){return!this.id},change:function(a){this.trigger("change",this,a);this._previousAttributes=f.clone(this.attributes);this._changed=false},hasChanged:function(a){if(a)return this._previousAttributes[a]!= -this.attributes[a];return this._changed},changedAttributes:function(a){a||(a=this.attributes);var b=this._previousAttributes,c=false,d;for(d in a)if(!f.isEqual(b[d],a[d])){c=c||{};c[d]=a[d]}return c},previous:function(a){if(!a||!this._previousAttributes)return null;return this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},_performValidation:function(a,b){var c=this.validate(a);if(c){b.error?b.error(this,c):this.trigger("error",this,c,b);return false}return true}}); -e.Collection=function(a,b){b||(b={});if(b.comparator){this.comparator=b.comparator;delete b.comparator}this._boundOnModelEvent=f.bind(this._onModelEvent,this);this._reset();a&&this.refresh(a,{silent:true});this.initialize(a,b)};f.extend(e.Collection.prototype,e.Events,{model:e.Model,initialize:function(){},toJSON:function(){return this.map(function(a){return a.toJSON()})},add:function(a,b){if(f.isArray(a))for(var c=0,d=a.length;c').hide().appendTo("body")[0].contentWindow; -"onhashchange"in window&&!a?h(window).bind("hashchange",this.checkUrl):setInterval(this.checkUrl,this.interval);return this.loadUrl()},route:function(a,b){this.handlers.push({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();if(a==this.fragment&&this.iframe)a=this.getFragment(this.iframe.location);if(a==this.fragment||a==decodeURIComponent(this.fragment))return false;if(this.iframe)window.location.hash=this.iframe.location.hash=a;this.loadUrl()},loadUrl:function(){var a=this.fragment= -this.getFragment();return f.any(this.handlers,function(b){if(b.route.test(a)){b.callback(a);return true}})},saveLocation:function(a){a=(a||"").replace(l,"");if(this.fragment!=a){window.location.hash=this.fragment=a;if(this.iframe&&a!=this.getFragment(this.iframe.location)){this.iframe.document.open().close();this.iframe.location.hash=a}}}});e.View=function(a){this._configure(a||{});this._ensureElement();this.delegateEvents();this.initialize(a)};var q=/^(\w+)\s*(.*)$/;f.extend(e.View.prototype,e.Events, -{tagName:"div",$:function(a){return h(a,this.el)},initialize:function(){},render:function(){return this},remove:function(){h(this.el).remove();return this},make:function(a,b,c){a=document.createElement(a);b&&h(a).attr(b);c&&h(a).html(c);return a},delegateEvents:function(a){if(a||(a=this.events)){h(this.el).unbind();for(var b in a){var c=a[b],d=b.match(q),g=d[1];d=d[2];c=f.bind(this[c],this);d===""?h(this.el).bind(g,c):h(this.el).delegate(d,g,c)}}},_configure:function(a){if(this.options)a=f.extend({}, -this.options,a);if(a.model)this.model=a.model;if(a.collection)this.collection=a.collection;if(a.el)this.el=a.el;if(a.id)this.id=a.id;if(a.className)this.className=a.className;if(a.tagName)this.tagName=a.tagName;this.options=a},_ensureElement:function(){if(!this.el){var a={};if(this.id)a.id=this.id;if(this.className)a["class"]=this.className;this.el=this.make(this.tagName,a)}}});var m=function(a,b){var c=r(this,a,b);c.extend=m;return c};e.Model.extend=e.Collection.extend=e.Controller.extend=e.View.extend= -m;var s={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};e.sync=function(a,b,c,d){var g=s[a];a=a==="create"||a==="update"?JSON.stringify(b.toJSON()):null;b={url:k(b),type:g,contentType:"application/json",data:a,dataType:"json",processData:false,success:c,error:d};if(e.emulateJSON){b.contentType="application/x-www-form-urlencoded";b.processData=true;b.data=a?{model:a}:{}}if(e.emulateHTTP)if(g==="PUT"||g==="DELETE"){if(e.emulateJSON)b.data._method=g;b.type="POST";b.beforeSend=function(i){i.setRequestHeader("X-HTTP-Method-Override", -g)}}h.ajax(b)};var n=function(){},r=function(a,b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){return a.apply(this,arguments)};n.prototype=a.prototype;d.prototype=new n;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},k=function(a){if(!(a&&a.url))throw Error("A 'url' property or function must be specified");return f.isFunction(a.url)?a.url():a.url},j=function(a,b,c){return function(d){a?a(b,d):b.trigger("error",b,d,c)}}})(); diff --git a/NuGet/ServiceStack.Host.AspNet/content/web.config.transform b/NuGet/ServiceStack.Host.AspNet/content/web.config.transform deleted file mode 100644 index 0b4a8586dc0..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/content/web.config.transform +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/NuGet/ServiceStack.Host.AspNet/servicestack.host.aspnet.nuspec b/NuGet/ServiceStack.Host.AspNet/servicestack.host.aspnet.nuspec deleted file mode 100644 index af796f08bc4..00000000000 --- a/NuGet/ServiceStack.Host.AspNet/servicestack.host.aspnet.nuspec +++ /dev/null @@ -1,26 +0,0 @@ - - - - ServiceStack.Host.AspNet - Starter ASP.NET Website Template - ServiceStack at / - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - -Host ServiceStack in an existing ASP.NET web application at the root path '/'. -ServiceStack is a modern, high-performance, code-first web service framework promoting code and web services best practices. Simple, Fast, Elegant. Website: https://servicestack.net - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - Fast JSON XML CSV HTML SOAP JSV REST Web Service Framework MONO ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Host.Mvc/content/App_Start/AppHost.cs.pp b/NuGet/ServiceStack.Host.Mvc/content/App_Start/AppHost.cs.pp deleted file mode 100644 index 3db30ad0502..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/content/App_Start/AppHost.cs.pp +++ /dev/null @@ -1,96 +0,0 @@ -using System.Configuration; -using System.Web.Mvc; -using ServiceStack; -using ServiceStack.Auth; -using ServiceStack.Configuration; -using ServiceStack.Data; -using ServiceStack.Mvc; -using ServiceStack.OrmLite; - -[assembly: WebActivator.PreApplicationStartMethod(typeof($rootnamespace$.App_Start.AppHost), "Start")] - -//IMPORTANT: Add the line below to RouteConfig.RegisterRoutes(RouteCollection) in the Global.asax: -//routes.IgnoreRoute("api/{*pathInfo}"); -//More info on how to integrate with MVC: https://github.com/ServiceStack/ServiceStack/wiki/Mvc-integration - -/** - * Entire ServiceStack Starter Template configured with a 'Hello' Web Service and a 'Todo' Rest Service. - * - * Auto-Generated Metadata API page at: /metadata - * See other complete web service examples at: https://github.com/ServiceStack/ServiceStack.Examples - */ - -namespace $rootnamespace$.App_Start -{ - //A customizeable typed UserSession that can be extended with your own properties - //To access ServiceStack's Session, Cache, etc from MVC Controllers inherit from ControllerBase - public class CustomUserSession : AuthUserSession - { - public string CustomProperty { get; set; } - } - - public class AppHost - : AppHostBase - { - public AppHost() //Tell ServiceStack the name and where to find your web services - : base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly) { } - - public override void Configure(Funq.Container container) - { - //Set JSON web services to return idiomatic JSON camelCase properties - ServiceStack.Text.JsConfig.EmitCamelCaseNames = true; - - //Configure User Defined REST Paths - Routes - .Add("/hello") - .Add("/hello/{Name*}"); - - //Uncomment to change the default ServiceStack configuration - //SetConfig(new HostConfig - //{ - //}); - - //Enable Authentication - //ConfigureAuth(container); - - //Register all your dependencies - container.Register(new TodoRepository()); - - //Set MVC to use the same Funq IOC as ServiceStack - ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container)); - } - - /* Uncomment to enable ServiceStack Authentication and CustomUserSession */ - private void ConfigureAuth(Funq.Container container) - { - var appSettings = new AppSettings(); - - //Default route: /auth/{provider} - Plugins.Add(new AuthFeature(() => new CustomUserSession(), - new IAuthProvider[] { - new CredentialsAuthProvider(appSettings), - new FacebookAuthProvider(appSettings), - new TwitterAuthProvider(appSettings), - new BasicAuthProvider(appSettings), - })); - - //Default route: /register - Plugins.Add(new RegistrationFeature()); - - //Requires ConnectionString configured in Web.Config - var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString; - container.Register(c => - new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider)); - - container.Register(c => - new OrmLiteAuthRepository(c.Resolve())); - - container.Resolve().InitSchema(); - } - - public static void Start() - { - new AppHost().Init(); - } - } -} diff --git a/NuGet/ServiceStack.Host.Mvc/content/README.txt b/NuGet/ServiceStack.Host.Mvc/content/README.txt deleted file mode 100644 index a02de2a60bd..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/content/README.txt +++ /dev/null @@ -1,48 +0,0 @@ -You *MUST* register ServiceStacks '/api' path by adding the lines below to MvcApplication.RegisterRoutes(RouteCollection) in the Global.asax: - - routes.IgnoreRoute("api/{*pathInfo}"); - routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); //Prevent exceptions for favicon - -Place them before the current entries the method. - -For MVC4 applications you also need to unregister WebApi, by commenting out this line: - - //WebApiConfig.Register(GlobalConfiguration.Configuration); - - -To enable the Mini Profiler add the following lines in to MvcApplication in Global.asax.cs: - - protected void Application_BeginRequest(object src, EventArgs e) - { - if (Request.IsLocal) - ServiceStack.MiniProfiler.Profiler.Start(); - } - - protected void Application_EndRequest(object src, EventArgs e) - { - ServiceStack.MiniProfiler.Profiler.Stop(); - } - - -For more info on the MiniProfiler see v3.09 of the https://github.com/ServiceStack/ServiceStack/wiki/Release-Notes - - -The Urls for metadata page and included Services: - - * /api/metadata - Auto generated metadata pages - * /api/hello - Simple Hello World Service see: http://www.servicestack.net/ServiceStack.Hello/ - * /api/todos - Simple REST Service see: http://www.servicestack.net/Backbone.Todos/ - - * /default.htm - Backbone.js TODO application talking to the TODO REST service at /api/todos - - - -For more info about ServiceStack please visit: http://www.servicestack.net - -Feel free to ask questions about ServiceStack on: -http://stackoverflow.com/ - -or on the mailing Group at: -http://groups.google.com/group/servicestack - -Enjoy! \ No newline at end of file diff --git a/NuGet/ServiceStack.Host.Mvc/content/WebServiceExamples.cs.pp b/NuGet/ServiceStack.Host.Mvc/content/WebServiceExamples.cs.pp deleted file mode 100644 index 9f16bcd8c63..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/content/WebServiceExamples.cs.pp +++ /dev/null @@ -1,132 +0,0 @@ -using System.Linq; -using System.Collections.Generic; -using ServiceStack; - -namespace $rootnamespace$ -{ - //Request DTO - public class Hello - { - public string Name { get; set; } - } - - //Response DTO - public class HelloResponse - { - public string Result { get; set; } - public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized - } - - //Can be called via any endpoint or format, see: http://mono.servicestack.net/ServiceStack.Hello/ - public class HelloService : Service - { - public object Any(Hello request) - { - return new HelloResponse { Result = "Hello, " + request.Name }; - } - } - - //REST Resource DTO - [Route("/todos")] - [Route("/todos/{Ids}")] - public class Todos : IReturn> - { - public long[] Ids { get; set; } - public Todos(params long[] ids) - { - this.Ids = ids; - } - } - - [Route("/todos", "POST")] - [Route("/todos/{Id}", "PUT")] - public class Todo : IReturn - { - public long Id { get; set; } - public string Content { get; set; } - public int Order { get; set; } - public bool Done { get; set; } - } - - public class TodosService : Service - { - public TodoRepository Repository { get; set; } //Injected by IOC - - public object Get(Todos request) - { - return request.Ids.IsEmpty() - ? Repository.GetAll() - : Repository.GetByIds(request.Ids); - } - - public object Post(Todo todo) - { - return Repository.Store(todo); - } - - public object Put(Todo todo) - { - return Repository.Store(todo); - } - - public void Delete(Todos request) - { - Repository.DeleteByIds(request.Ids); - } - } - - public class TodoRepository - { - List todos = new List(); - - public List GetByIds(long[] ids) - { - return todos.Where(x => ids.Contains(x.Id)).ToList(); - } - - public List GetAll() - { - return todos; - } - - public Todo Store(Todo todo) - { - var existing = todos.FirstOrDefault(x => x.Id == todo.Id); - if (existing == null) - { - var newId = todos.Count > 0 ? todos.Max(x => x.Id) + 1 : 1; - todo.Id = newId; - todos.Add(todo); - } - else - { - existing.PopulateWith(todo); - } - return todo; - } - - public void DeleteByIds(params long[] ids) - { - todos.RemoveAll(x => ids.Contains(x.Id)); - } - } - - -/* Example calling above Service with ServiceStack's C# clients: - - var client = new JsonServiceClient(BaseUri); - List all = client.Get(new Todos()); // Count = 0 - - var todo = client.Post( - new Todo { Content = "New TODO", Order = 1 }); // todo.Id = 1 - all = client.Get(new Todos()); // Count = 1 - - todo.Content = "Updated TODO"; - todo = client.Put(todo); // todo.Content = Updated TODO - - client.Delete(new Todos(todo.Id)); - all = client.Get(new Todos()); // Count = 0 - -*/ - -} diff --git a/NuGet/ServiceStack.Host.Mvc/content/default.htm b/NuGet/ServiceStack.Host.Mvc/content/default.htm deleted file mode 100644 index a451c4f026a..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/content/default.htm +++ /dev/null @@ -1,685 +0,0 @@ - - - - - Backbone Demo: Todos - - - - - - - - - - - - -
    - -
    -

    Todos

    -
    - -
    - -
    - - -
    - -
    -
      -
      - -
      - -
      - -
      - - - -
      - Created by -
      - Jérôme Gravel-Niquet -
      -
      - Powered By Open Source -
      - servicestack.net - | redis - | mono -
      - - - - - - - - - - - - - - diff --git a/NuGet/ServiceStack.Host.Mvc/content/jqunback-1.51.min.js b/NuGet/ServiceStack.Host.Mvc/content/jqunback-1.51.min.js deleted file mode 100644 index 97da2a076f8..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/content/jqunback-1.51.min.js +++ /dev/null @@ -1,68 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function(a,b){function cg(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cd(a){if(!bZ[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bZ[a]=c}return bZ[a]}function cc(a,b){var c={};d.each(cb.concat.apply([],cb.slice(0,b)),function(){c[this]=a});return c}function bY(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bX(){try{return new a.XMLHttpRequest}catch(b){}}function bW(){d(a).unload(function(){for(var a in bU)bU[a](0,1)})}function bQ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(r,"`").replace(s,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,q=[],r=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function w(){return!0}function v(){return!1}function g(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.1",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1){var f=E.call(arguments,0),g=b,h=function(a){return function(b){f[a]=arguments.length>1?E.call(arguments,0):b,--g||c.resolveWith(e,f)}};while(b--)a=f[b],a&&d.isFunction(a.promise)?a.promise().then(h(b),c.reject):--g;g||c.resolveWith(e,f)}else c!==a&&c.resolve(a);return e},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="
      a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e),b=e=f=null}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
      ",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
      t
      ";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!g(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,h=b.nodeType,i=h?d.cache:b,j=h?b[d.expando]:d.expando;if(!i[j])return;if(c){var k=e?i[j][f]:i[j];if(k){delete k[c];if(!g(k))return}}if(e){delete i[j][f];if(!g(i[j]))return}var l=i[j][f];d.support.deleteExpando||i!=a?delete i[j]:i[j]=null,l?(i[j]={},h||(i[j].toJSON=d.noop),i[j][f]=l):h&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var k=i?f:0,l=i?f+1:h.length;k=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=k.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&l.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:m.test(a.nodeName)||n.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var p=/\.(.*)$/,q=/^(?:textarea|input|select)$/i,r=/\./g,s=/ /g,t=/[^\w\s.|`]/g,u=function(a){return a.replace(t,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=v;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),u).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(p,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(q.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return q.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return q.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.getAttribute("type")},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

      ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(d||!l.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return k(c,null,null,[a]).length>0})}(),function(){var a=c.createElement("div");a.innerHTML="
      ";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/",""],legend:[1,"
      ","
      "],thead:[1,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],col:[2,"","
      "],area:[1,"",""],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div
      ","
      "]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){$(a,e),f=_(a),g=_(e);for(h=0;f[h];++h)$(f[h],g[h])}if(b){Z(a,e);if(c){f=_(a),g=_(e);for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/)<[^<]*)*<\/script>/gi,bA=/^(?:select|textarea)/i,bB=/\s+/,bC=/([?&])_=[^&]*/,bD=/(^|\-)([a-z])/g,bE=function(a,b,c){return b+c.toUpperCase()},bF=/^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/,bG=d.fn.load,bH={},bI={},bJ,bK;try{bJ=c.location.href}catch(bL){bJ=c.createElement("a"),bJ.href="",bJ=bJ.href}bK=bF.exec(bJ.toLowerCase()),d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bG)return bG.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
      ").append(c.replace(bz,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bA.test(this.nodeName)||bu.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(br,"\r\n")}}):{name:b.name,value:c.replace(br,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bJ,isLocal:bv.test(bK[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bM(bH),ajaxTransport:bM(bI),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bP(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bQ(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bD,bE)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bt.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bs,"").replace(bx,bK[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bB),e.crossDomain||(q=bF.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bK[1]||q[2]!=bK[2]||(q[3]||(q[1]==="http:"?80:443))!=(bK[3]||(bK[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bN(bH,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!bw.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(by.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bC,"$1_="+w);e.url=x+(x===e.url?(by.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bN(bI,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bO(g,a[g],c,f);return e.join("&").replace(bp,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bR=d.now(),bS=/(\=)\?(&|$)|()\?\?()/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bR++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bS.test(b.url)||f&&bS.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bS,l),b.url===j&&(f&&(k=k.replace(bS,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bT=d.now(),bU,bV;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bX()||bY()}:bX,bV=d.ajaxSettings.xhr(),d.support.ajax=!!bV,d.support.cors=bV&&"withCredentials"in bV,bV=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),(!a.crossDomain||a.hasContent)&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bU[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bU||(bU={},bW()),h=bT++,g.onreadystatechange=bU[h]=c):c()},abort:function(){c&&c(0,1)}}}});var bZ={},b$=/^(?:toggle|show|hide)$/,b_=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,ca,cb=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(cc("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:cc("show",1),slideUp:cc("hide",1),slideToggle:cc("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!ca&&(ca=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
      ";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=cf.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!cf.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=cg(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=cg(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window);// Underscore.js 1.1.5 -// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore -(function(){var q=this,D=q._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,E=k.unshift,F=o.toString,m=o.hasOwnProperty,s=k.forEach,t=k.map,u=k.reduce,v=k.reduceRight,w=k.filter,x=k.every,y=k.some,p=k.indexOf,z=k.lastIndexOf;o=Array.isArray;var G=Object.keys,A=Function.prototype.bind,c=function(a){return new l(a)};if(typeof module!=="undefined"&&module.exports){module.exports=c;c._=c}else q._=c;c.VERSION="1.1.5";var j=c.each=c.forEach=function(a,b,d){if(a!=null)if(s&&a.forEach===s)a.forEach(b, -d);else if(c.isNumber(a.length))for(var e=0,f=a.length;e=e.computed&&(e={value:f,computed:g})});return e.value};c.min=function(a,b,d){if(!b&&c.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};j(a,function(f,g,h){g=b?b.call(d,f,g,h):f;gh?1:0}),"value")};c.sortedIndex= -function(a,b,d){d=d||c.identity;for(var e=0,f=a.length;e>1;d(a[g])=0})})};c.zip=function(){for(var a=i.call(arguments),b=c.max(c.pluck(a,"length")),d=Array(b),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};c.keys=G||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)if(m.call(a, -d))b[b.length]=d;return b};c.values=function(a){return c.map(a,c.identity)};c.functions=c.methods=function(a){return c.filter(c.keys(a),function(b){return c.isFunction(a[b])}).sort()};c.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};c.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)if(a[d]==null)a[d]=b[d]});return a};c.clone=function(a){return c.isArray(a)?a.slice():c.extend({},a)};c.tap=function(a,b){b(a);return a};c.isEqual=function(a, -b){if(a===b)return true;var d=typeof a;if(d!=typeof b)return false;if(a==b)return true;if(!a&&b||a&&!b)return false;if(a._chain)a=a._wrapped;if(b._chain)b=b._wrapped;if(a.isEqual)return a.isEqual(b);if(c.isDate(a)&&c.isDate(b))return a.getTime()===b.getTime();if(c.isNaN(a)&&c.isNaN(b))return false;if(c.isRegExp(a)&&c.isRegExp(b))return a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline;if(d!=="object")return false;if(a.length&&a.length!==b.length)return false; -d=c.keys(a);var e=c.keys(b);if(d.length!=e.length)return false;for(var f in a)if(!(f in b)||!c.isEqual(a[f],b[f]))return false;return true};c.isEmpty=function(a){if(c.isArray(a)||c.isString(a))return a.length===0;for(var b in a)if(m.call(a,b))return false;return true};c.isElement=function(a){return!!(a&&a.nodeType==1)};c.isArray=o||function(a){return F.call(a)==="[object Array]"};c.isArguments=function(a){return!!(a&&m.call(a,"callee"))};c.isFunction=function(a){return!!(a&&a.constructor&&a.call&& -a.apply)};c.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};c.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};c.isNaN=function(a){return a!==a};c.isBoolean=function(a){return a===true||a===false};c.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};c.isRegExp=function(a){return!!(a&&a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};c.isNull=function(a){return a===null};c.isUndefined=function(a){return a===void 0};c.noConflict=function(){q._= -D;return this};c.identity=function(a){return a};c.times=function(a,b,d){for(var e=0;e/g,interpolate:/<%=([\s\S]+?)%>/g};c.template=function(a,b){var d=c.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate, -function(e,f){return"',"+f.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(e,f){return"');"+f.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return b?d(b):d};var l=function(a){this._wrapped=a};c.prototype=l.prototype;var r=function(a,b){return b?c(a).chain():a},I=function(a,b){l.prototype[a]=function(){var d=i.call(arguments);E.call(d,this._wrapped);return r(b.apply(c, -d),this._chain)}};c.mixin(c);j(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=k[a];l.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];l.prototype[a]=function(){return r(b.apply(this._wrapped,arguments),this._chain)}});l.prototype.chain=function(){this._chain=true;return this};l.prototype.value=function(){return this._wrapped}})(); -// Backbone.js 0.3.3 -// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc. -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://documentcloud.github.com/backbone -(function(){var e;e=typeof exports!=="undefined"?exports:this.Backbone={};e.VERSION="0.3.3";var f=this._;if(!f&&typeof require!=="undefined")f=require("underscore")._;var h=this.jQuery||this.Zepto;e.emulateHTTP=false;e.emulateJSON=false;e.Events={bind:function(a,b){this._callbacks||(this._callbacks={});(this._callbacks[a]||(this._callbacks[a]=[])).push(b);return this},unbind:function(a,b){var c;if(a){if(c=this._callbacks)if(b){c=c[a];if(!c)return this;for(var d=0,g=c.length;d/g,">").replace(/"/g, -""")},set:function(a,b){b||(b={});if(!a)return this;if(a.attributes)a=a.attributes;var c=this.attributes,d=this._escapedAttributes;if(!b.silent&&this.validate&&!this._performValidation(a,b))return false;if("id"in a)this.id=a.id;for(var g in a){var i=a[g];if(!f.isEqual(c[g],i)){c[g]=i;delete d[g];if(!b.silent){this._changed=true;this.trigger("change:"+g,this,i,b)}}}!b.silent&&this._changed&&this.change(b);return this},unset:function(a,b){b||(b={});var c={};c[a]=void 0;if(!b.silent&&this.validate&& -!this._performValidation(c,b))return false;delete this.attributes[a];delete this._escapedAttributes[a];if(!b.silent){this._changed=true;this.trigger("change:"+a,this,void 0,b);this.change(b)}return this},clear:function(a){a||(a={});var b=this.attributes,c={};for(attr in b)c[attr]=void 0;if(!a.silent&&this.validate&&!this._performValidation(c,a))return false;this.attributes={};this._escapedAttributes={};if(!a.silent){this._changed=true;for(attr in b)this.trigger("change:"+attr,this,void 0,a);this.change(a)}return this}, -fetch:function(a){a||(a={});var b=this,c=j(a.error,b,a);(this.sync||e.sync)("read",this,function(d){if(!b.set(b.parse(d),a))return false;a.success&&a.success(b,d)},c);return this},save:function(a,b){b||(b={});if(a&&!this.set(a,b))return false;var c=this,d=j(b.error,c,b),g=this.isNew()?"create":"update";(this.sync||e.sync)(g,this,function(i){if(!c.set(c.parse(i),b))return false;b.success&&b.success(c,i)},d);return this},destroy:function(a){a||(a={});var b=this,c=j(a.error,b,a);(this.sync||e.sync)("delete", -this,function(d){b.collection&&b.collection.remove(b);a.success&&a.success(b,d)},c);return this},url:function(){var a=k(this.collection);if(this.isNew())return a;return a+(a.charAt(a.length-1)=="/"?"":"/")+this.id},parse:function(a){return a},clone:function(){return new this.constructor(this)},isNew:function(){return!this.id},change:function(a){this.trigger("change",this,a);this._previousAttributes=f.clone(this.attributes);this._changed=false},hasChanged:function(a){if(a)return this._previousAttributes[a]!= -this.attributes[a];return this._changed},changedAttributes:function(a){a||(a=this.attributes);var b=this._previousAttributes,c=false,d;for(d in a)if(!f.isEqual(b[d],a[d])){c=c||{};c[d]=a[d]}return c},previous:function(a){if(!a||!this._previousAttributes)return null;return this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},_performValidation:function(a,b){var c=this.validate(a);if(c){b.error?b.error(this,c):this.trigger("error",this,c,b);return false}return true}}); -e.Collection=function(a,b){b||(b={});if(b.comparator){this.comparator=b.comparator;delete b.comparator}this._boundOnModelEvent=f.bind(this._onModelEvent,this);this._reset();a&&this.refresh(a,{silent:true});this.initialize(a,b)};f.extend(e.Collection.prototype,e.Events,{model:e.Model,initialize:function(){},toJSON:function(){return this.map(function(a){return a.toJSON()})},add:function(a,b){if(f.isArray(a))for(var c=0,d=a.length;c').hide().appendTo("body")[0].contentWindow; -"onhashchange"in window&&!a?h(window).bind("hashchange",this.checkUrl):setInterval(this.checkUrl,this.interval);return this.loadUrl()},route:function(a,b){this.handlers.push({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();if(a==this.fragment&&this.iframe)a=this.getFragment(this.iframe.location);if(a==this.fragment||a==decodeURIComponent(this.fragment))return false;if(this.iframe)window.location.hash=this.iframe.location.hash=a;this.loadUrl()},loadUrl:function(){var a=this.fragment= -this.getFragment();return f.any(this.handlers,function(b){if(b.route.test(a)){b.callback(a);return true}})},saveLocation:function(a){a=(a||"").replace(l,"");if(this.fragment!=a){window.location.hash=this.fragment=a;if(this.iframe&&a!=this.getFragment(this.iframe.location)){this.iframe.document.open().close();this.iframe.location.hash=a}}}});e.View=function(a){this._configure(a||{});this._ensureElement();this.delegateEvents();this.initialize(a)};var q=/^(\w+)\s*(.*)$/;f.extend(e.View.prototype,e.Events, -{tagName:"div",$:function(a){return h(a,this.el)},initialize:function(){},render:function(){return this},remove:function(){h(this.el).remove();return this},make:function(a,b,c){a=document.createElement(a);b&&h(a).attr(b);c&&h(a).html(c);return a},delegateEvents:function(a){if(a||(a=this.events)){h(this.el).unbind();for(var b in a){var c=a[b],d=b.match(q),g=d[1];d=d[2];c=f.bind(this[c],this);d===""?h(this.el).bind(g,c):h(this.el).delegate(d,g,c)}}},_configure:function(a){if(this.options)a=f.extend({}, -this.options,a);if(a.model)this.model=a.model;if(a.collection)this.collection=a.collection;if(a.el)this.el=a.el;if(a.id)this.id=a.id;if(a.className)this.className=a.className;if(a.tagName)this.tagName=a.tagName;this.options=a},_ensureElement:function(){if(!this.el){var a={};if(this.id)a.id=this.id;if(this.className)a["class"]=this.className;this.el=this.make(this.tagName,a)}}});var m=function(a,b){var c=r(this,a,b);c.extend=m;return c};e.Model.extend=e.Collection.extend=e.Controller.extend=e.View.extend= -m;var s={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};e.sync=function(a,b,c,d){var g=s[a];a=a==="create"||a==="update"?JSON.stringify(b.toJSON()):null;b={url:k(b),type:g,contentType:"application/json",data:a,dataType:"json",processData:false,success:c,error:d};if(e.emulateJSON){b.contentType="application/x-www-form-urlencoded";b.processData=true;b.data=a?{model:a}:{}}if(e.emulateHTTP)if(g==="PUT"||g==="DELETE"){if(e.emulateJSON)b.data._method=g;b.type="POST";b.beforeSend=function(i){i.setRequestHeader("X-HTTP-Method-Override", -g)}}h.ajax(b)};var n=function(){},r=function(a,b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){return a.apply(this,arguments)};n.prototype=a.prototype;d.prototype=new n;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},k=function(a){if(!(a&&a.url))throw Error("A 'url' property or function must be specified");return f.isFunction(a.url)?a.url():a.url},j=function(a,b,c){return function(d){a?a(b,d):b.trigger("error",b,d,c)}}})(); diff --git a/NuGet/ServiceStack.Host.Mvc/content/web.config.transform b/NuGet/ServiceStack.Host.Mvc/content/web.config.transform deleted file mode 100644 index bf9e6a08ec6..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/content/web.config.transform +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/NuGet/ServiceStack.Host.Mvc/servicestack.host.mvc.nuspec b/NuGet/ServiceStack.Host.Mvc/servicestack.host.mvc.nuspec deleted file mode 100644 index 0fb46979f3f..00000000000 --- a/NuGet/ServiceStack.Host.Mvc/servicestack.host.mvc.nuspec +++ /dev/null @@ -1,27 +0,0 @@ - - - - ServiceStack.Host.Mvc - Starter ASP.NET MVC Website Template - ServiceStack at /api - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - -Host ServiceStack side-by-side with an existing ASP.NET MVC application at the path '/api'. -ServiceStack is a modern, high-performance, code-first web service framework promoting code and web services best practices. Simple, Fast, Elegant. Website: https://servicestack.net - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - Fast JSON XML CSV HTML SOAP JSV REST Web Service Framework MONO ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.HttpClient/servicestack.httpclient.nuspec b/NuGet/ServiceStack.HttpClient/servicestack.httpclient.nuspec deleted file mode 100644 index 4724b99e8f2..00000000000 --- a/NuGet/ServiceStack.HttpClient/servicestack.httpclient.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.HttpClient - JSON HttpClient for ServiceStack - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - JSON ServiceClient implementation based on .NET's HttpClient - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - ServiceStack Common Framework Clients ServiceClients JSON HttpClient Gateway - en-US - Copyright 2016 Service Stack - - - - - - - - - - diff --git a/NuGet/ServiceStack.Interfaces/servicestack.interfaces.nuspec b/NuGet/ServiceStack.Interfaces/servicestack.interfaces.nuspec deleted file mode 100644 index ca09a4df9a2..00000000000 --- a/NuGet/ServiceStack.Interfaces/servicestack.interfaces.nuspec +++ /dev/null @@ -1,26 +0,0 @@ - - - - ServiceStack.Interfaces - Lightweight and implementation-free interfaces for ServiceStack - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Lightweight and implementation-free interfaces for DTO's, providers and adapters. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - Fast JSON XML CSV HTML SOAP JSV REST Web Service Framework MONO ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Logging.Elmah/servicestack.logging.elmah.nuspec b/NuGet/ServiceStack.Logging.Elmah/servicestack.logging.elmah.nuspec deleted file mode 100644 index c7905e1ad75..00000000000 --- a/NuGet/ServiceStack.Logging.Elmah/servicestack.logging.elmah.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.Logging.Elmah - 4.5.0 - ServiceStack.Logging.Elmah - Service Stack - Service Stack - Elmah logging integration for ServiceStack, the Opensource .NET and Mono REST Web Services Framework - false - - Provides Elmah logging integration for other ServiceStack projects - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - servicestack log logging elmah - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Logging.EntLib5/servicestack.logging.entlib5.nuspec b/NuGet/ServiceStack.Logging.EntLib5/servicestack.logging.entlib5.nuspec deleted file mode 100644 index 95318852b7a..00000000000 --- a/NuGet/ServiceStack.Logging.EntLib5/servicestack.logging.entlib5.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.Logging.EntLib5 - 4.5.0 - ServiceStack.Logging.EntLib5 - Service Stack - Service Stack - Enterprise Library 5.0 Logging Application Block integration for ServiceStack, the Opensource .NET and Mono REST Web Services Framework - false - - Provides Enterprise Library 5.0 Logging Application Block logging integration for other ServiceStack projects - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - servicestack log logging nlog - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Logging.EventLog/servicestack.logging.eventlog.nuspec b/NuGet/ServiceStack.Logging.EventLog/servicestack.logging.eventlog.nuspec deleted file mode 100644 index f3910e33464..00000000000 --- a/NuGet/ServiceStack.Logging.EventLog/servicestack.logging.eventlog.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.Logging.EventLog - 4.5.0 - ServiceStack.Logging.EventLog - Service Stack - Service Stack - Windows Event Log integration for ServiceStack, the Opensource .NET and Mono REST Web Services Framework - false - - Provides EventLog logging integration for other ServiceStack projects - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - servicestack log logging eventlog - en-US - Copyright 2016 Service Stack - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Logging.Log4Net/servicestack.logging.log4net.nuspec b/NuGet/ServiceStack.Logging.Log4Net/servicestack.logging.log4net.nuspec deleted file mode 100644 index bcc59f10e1d..00000000000 --- a/NuGet/ServiceStack.Logging.Log4Net/servicestack.logging.log4net.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.Logging.Log4Net - 4.5.0 - ServiceStack.Logging.Log4Net - Service Stack - Service Stack - log4Net logging integration for ServiceStack, the Opensource .NET and Mono REST Web Services Framework - false - - Provides log4net logging integration for other ServiceStack projects - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - servicestack log logging log4net - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Logging.NLog/servicestack.logging.nlog.nuspec b/NuGet/ServiceStack.Logging.NLog/servicestack.logging.nlog.nuspec deleted file mode 100644 index d8f4e97387a..00000000000 --- a/NuGet/ServiceStack.Logging.NLog/servicestack.logging.nlog.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.Logging.NLog - 4.5.0 - ServiceStack.Logging.NLog - Service Stack - Service Stack - NLog logging integration for ServiceStack, the Opensource .NET and Mono REST Web Services Framework - false - - Provides NLog logging integration for other ServiceStack projects - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - servicestack log logging nlog - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Logging.Slack/servicestack.logging.slack.nuspec b/NuGet/ServiceStack.Logging.Slack/servicestack.logging.slack.nuspec deleted file mode 100644 index f48c22150f7..00000000000 --- a/NuGet/ServiceStack.Logging.Slack/servicestack.logging.slack.nuspec +++ /dev/null @@ -1,29 +0,0 @@ - - - - ServiceStack.Logging.Slack - 4.5.0 - ServiceStack.Logging.Slack - Service Stack - Service Stack - Slack logging provider for ServiceStack - false - - Provides Slack logging provider for ServiceStack projects - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - servicestack slack log logging logger provider adapter - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.MsgPack/servicestack.msgpack.nuspec b/NuGet/ServiceStack.MsgPack/servicestack.msgpack.nuspec deleted file mode 100644 index 50bc34aeefa..00000000000 --- a/NuGet/ServiceStack.MsgPack/servicestack.msgpack.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.MsgPack - Message Pack support for ServiceStack. Includes typed MsgPack Client - 4.5.0 - Service Stack - Service Stack - MsgPack Format Serializer ContentType ServiceClients for ServiceStack - - Add the MsgPack binary format and endpoint to a ServiceStack web service host. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - MsgPack MessagePack Message Pack Fast Binary Serializer Format ContentType REST Web Services ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Mvc/servicestack.mvc.nuspec b/NuGet/ServiceStack.Mvc/servicestack.mvc.nuspec deleted file mode 100644 index d10c3a4cbed..00000000000 --- a/NuGet/ServiceStack.Mvc/servicestack.mvc.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - ServiceStack.Mvc - MVC Adapters for integrating with ServiceStack webservices - 4.5.0 - Service Stack - Service Stack - ASP.NET MVC Integration adapters for ServiceStack - - Full details in MVC PowerPack: http://mono.servicestack.net/mvc-powerpack/ - MVC Adapter classes to provide tight integration and re-usable functionality between ServiceStack and MVC. - Including adapters for: MiniProfiler, FluentValidation, Funq IOC Controller Factory, Funq Validator Factory - ControllerBase (configured with access to ServiceStack's ICacheClient, ISession, typed UserSession dependencies). - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - MVC ServiceStack MiniProfiler FluentValidation Controller - en-US - Copyright 2016 Service Stack - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.ProtoBuf/servicestack.protobuf.nuspec b/NuGet/ServiceStack.ProtoBuf/servicestack.protobuf.nuspec deleted file mode 100644 index 62c11bf6c48..00000000000 --- a/NuGet/ServiceStack.ProtoBuf/servicestack.protobuf.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - ServiceStack.ProtoBuf - Protocol Buffers support for ServiceStack. Includes typed ProtoBuf Client - 4.5.0 - Service Stack - Service Stack - ProtoBuf Format Serializer ContentType ServiceClients for ServiceStack - - Add the ProtoBuf binary format and endpoint to a ServiceStack web service host. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - https://servicestack.net/img/logo-32.png - ProtoBuf Fast Binary Serializer Format ContentType REST Web Services ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.RabbitMq/servicestack.rabbitmq.nuspec b/NuGet/ServiceStack.RabbitMq/servicestack.rabbitmq.nuspec deleted file mode 100644 index 21e3ef9adf7..00000000000 --- a/NuGet/ServiceStack.RabbitMq/servicestack.rabbitmq.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - ServiceStack.RabbitMq - ServiceStack.RabbitMq - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Rabbit MQ client and server adapters for the ServiceStack web services framework. - This library enables consuming and publishing to ServiceStack services when hosted within a Rabbit MQ Server Host. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - MQ Message Queue Web Service Framework Fast JSON MONO ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Razor.BuildTask/build/ServiceStack.Razor.BuildTask.targets b/NuGet/ServiceStack.Razor.BuildTask/build/ServiceStack.Razor.BuildTask.targets deleted file mode 100644 index 799dc3c07d9..00000000000 --- a/NuGet/ServiceStack.Razor.BuildTask/build/ServiceStack.Razor.BuildTask.targets +++ /dev/null @@ -1,25 +0,0 @@ - - - $(CoreCompileDependsOn);RazorGeneratorOutput - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Razor.BuildTask/servicestack.razor.buildtask.nuspec b/NuGet/ServiceStack.Razor.BuildTask/servicestack.razor.buildtask.nuspec deleted file mode 100644 index 687b5c4a2a4..00000000000 --- a/NuGet/ServiceStack.Razor.BuildTask/servicestack.razor.buildtask.nuspec +++ /dev/null @@ -1,31 +0,0 @@ - - - - ServiceStack.Razor.BuildTask - ServiceStack.Razor.BuildTask - MSBuild Task to compile Razor Views as a build-step - 4.5.0 - Service Stack - Service Stack - MSBuild Task to generate and compile Service Stack Razor Views as a build-step, ready for instant use at run-time - - ServiceStack Razor Documentation: http://razor.servicestack.net - - Compile Razor Views into a compiled .dll you can use in ServiceStack hosts to eliminate Razor View compilation at runtime for instant start-up times. - - http://razor.servicestack.net - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - Razor ViewEngine View Templates Controllers Mono ASP.NET Self-Host ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Razor.BuildTask/tools/install.ps1 b/NuGet/ServiceStack.Razor.BuildTask/tools/install.ps1 deleted file mode 100644 index 292726d57ea..00000000000 --- a/NuGet/ServiceStack.Razor.BuildTask/tools/install.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -param($installPath, $toolsPath, $package, $project) - -# Set BuildAction of Razor Views to Content -function CompileRazorViews($projectItems) { - $projectItems | %{ - $x = $_.Name.ToLower() - if ($x -like "*.cshtml") { - $_.Properties.Item("BuildAction").Value = [int]2 # Content - } - - # Recursively - if ($_.ProjectItems) { - CompileRazorViews $_.ProjectItems - } - } -} - -# Embed Resource Files -function EmbedResources($projectItems) { - $projectItems | %{ - $x = $_.Name.ToLower() - if ($x -like "*.md" -or $x -like "*.js" -or $x -like "*.css") { - $_.Properties.Item("BuildAction").Value = [int]3 # Embed - } - elseif ($x -like "*.png" -or $x -like "*.gif" -or $x -like "*.jpg" -or $x -like "*.jpeg") { - $_.Properties.Item("BuildAction").Value = [int]3 # Embed - } - - # Recursively - if ($_.ProjectItems) { - EmbedResources $_.ProjectItems - } - } -} - -CompileRazorViews $project.ProjectItems -#EmbedResources $project.ProjectItems - diff --git a/NuGet/ServiceStack.Razor.BuildTask/tools/uninstall.ps1 b/NuGet/ServiceStack.Razor.BuildTask/tools/uninstall.ps1 deleted file mode 100644 index 750d3ccbfc0..00000000000 --- a/NuGet/ServiceStack.Razor.BuildTask/tools/uninstall.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -param($installPath, $toolsPath, $package, $project) - -<# -$targetsFileName = 'ServiceStack.Razor.BuildTask.targets'; - -# Need to load MSBuild assembly if it's not loaded yet. -Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' - -# Grab the loaded MSBuild project for the project -$msbuild = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName) | Select-Object -First 1 - -# Remove imports to .targets -$msbuild.Xml.Imports | Where-Object {$_.Project.ToLowerInvariant().EndsWith($targetsFileName.ToLowerInvariant()) } | Foreach { - $_.Parent.RemoveChild( $_ ) - [string]::Format( "Removed import of '{0}'" , $_.Project ) -} -#> \ No newline at end of file diff --git a/NuGet/ServiceStack.Razor/content/web.config.transform b/NuGet/ServiceStack.Razor/content/web.config.transform deleted file mode 100644 index 5632e54d8e1..00000000000 --- a/NuGet/ServiceStack.Razor/content/web.config.transform +++ /dev/null @@ -1,35 +0,0 @@ - - - - -
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Razor/servicestack.razor.nuspec b/NuGet/ServiceStack.Razor/servicestack.razor.nuspec deleted file mode 100644 index 5ac39819948..00000000000 --- a/NuGet/ServiceStack.Razor/servicestack.razor.nuspec +++ /dev/null @@ -1,42 +0,0 @@ - - - - ServiceStack.Razor - ServiceStack.Razor - ServiceStack's HTML story including MVC Razor - 4.5.0 - Service Stack - Service Stack - Provides ServiceStack's HTML Story including integrated support for MVC Razor's ViewEngine - - ServiceStack Razor Documentation: http://razor.servicestack.net - - - Turns ServiceStack into a Complete Web + REST Services Stack. Replaces need for ASP.NET MVC. - - Runs In ASP.NET or Self-host, first-class cross-platform support on .NET / Mono runtimes. - - Add HTML views to existing services. - - Change Views and Layout templates at runtime. - - No Ceremony development options - Pages without controllers, with typed and dynamic View Models. - - Include Partial Markdown views in Razor pages. - - Cascading Layout templates. - - Pretty urls by default (no custom Routes needed). - - Keep all views and assets together. - - Smart View Pages. - - http://razor.servicestack.net - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - Razor ViewEngine View Templates Controllers Mono ASP.NET Self-Host ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack.Server/servicestack.server.nuspec b/NuGet/ServiceStack.Server/servicestack.server.nuspec deleted file mode 100644 index fbd80fea6e2..00000000000 --- a/NuGet/ServiceStack.Server/servicestack.server.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - ServiceStack.Server - ServiceStack Server integration with Redis and OrmLite - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Integration libraries and adapters with other major ServiceStack server components. - Includes high-level API's that use OrmLite and Redis including: - AutoQuery, Redis MQ, OrmLiteAuthRepository, OrmLiteCacheClient, OrmLiteAppSettings, - RedisServerEvents and RedisRequestLogger. - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - ServiceStack AutoQuery OrmLite Redis MQ Caching ServerEvents - en-US - Copyright 2016 Service Stack - - - - - - - - - - - \ No newline at end of file diff --git a/NuGet/ServiceStack/servicestack.nuspec b/NuGet/ServiceStack/servicestack.nuspec deleted file mode 100644 index b8973f71810..00000000000 --- a/NuGet/ServiceStack/servicestack.nuspec +++ /dev/null @@ -1,38 +0,0 @@ - - - - ServiceStack - ServiceStack webservice framework: Faster, Cleaner, Modern WCF alternative - 4.5.0 - Service Stack - Service Stack - Opensource .NET and Mono REST Web Services framework - - Binaries for the ServiceStack web framework. - - A simple and fast alternative to WCF, MVC and Web API in one cohesive framework for all your services and web apps that's intuitive and Easy to use! - - To get started see: https://servicestack.net/getting-started - - https://github.com/ServiceStack/ServiceStack - https://servicestack.net/terms - true - https://servicestack.net/img/logo-32.png - Fast JSON XML CSV HTML SOAP JSV REST Web Service Framework MONO ServiceStack - en-US - Copyright 2016 Service Stack - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index a085b4b2040..3ec4d2599f8 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,109 @@ -Join the [ServiceStack Google+ Community](https://plus.google.com/communities/112445368900682590445) or follow [@ServiceStack](https://twitter.com/servicestack) for updates. +Follow [@ServiceStack](https://twitter.com/servicestack) or [view the docs](https://docs.servicestack.net), use [StackOverflow](http://stackoverflow.com/questions/ask) or the [Customer Forums](https://forums.servicestack.net/) for support. -> View the [Release Notes](https://servicestack.net/release-notes) for latest features or see [servicestack.net/features](https://servicestack.net/features) for an overview. +> View the [Release Notes](https://docs.servicestack.net/release-notes-history) for latest features or see [servicestack.net/features](https://servicestack.net/features) for an overview. ### Simple, Fast, Versatile and full-featured Services Framework ServiceStack is a simple, fast, versatile and highly-productive full-featured [Web](http://razor.servicestack.net) and -[Web Services](https://github.com/ServiceStack/ServiceStack/wiki/Service-Stack-Web-Services) Framework that's -thoughtfully-architected to [reduce artificial complexity](https://github.com/ServiceStack/ServiceStack/wiki/Why-not-OData#why-not-complexity) and promote -[remote services best-practices](https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services) -with a [message-based design](https://github.com/ServiceStack/ServiceStack/wiki/What-is-a-message-based-web-service) +[Web Services](https://docs.servicestack.net/web-services.html) Framework that's +thoughtfully-architected to [reduce artificial complexity](https://docs.servicestack.net/why-not-odata.html#why-not-complexity) and promote +[remote services best-practices](https://docs.servicestack.net/advantages-of-message-based-web-services.html) +with a [message-based design](https://docs.servicestack.net/what-is-a-message-based-web-service.html) that allows for maximum re-use that can leverage an integrated -[Service Gateway](https://github.com/ServiceStack/ServiceStack/wiki/Service-Gateway) +[Service Gateway](https://docs.servicestack.net/service-gateway.html) for the creation of loosely-coupled -[Modularized Service](https://github.com/ServiceStack/ServiceStack/wiki/Modularizing-services) Architectures. +[Modularized Service](https://docs.servicestack.net/modularizing-services.html) Architectures. ServiceStack Services are consumable via an array of built-in fast data formats (inc. [JSON](https://github.com/ServiceStack/ServiceStack.Text), XML, -[CSV](https://github.com/ServiceStack/ServiceStack/wiki/CSV-Format), -[JSV](https://github.com/ServiceStack/ServiceStack.Text/wiki/JSV-Format), -[ProtoBuf](https://github.com/ServiceStack/ServiceStack/wiki/Protobuf-format) and -[MsgPack](https://github.com/ServiceStack/ServiceStack/wiki/MessagePack-Format)) -as well as XSD/WSDL for [SOAP endpoints](https://github.com/ServiceStack/ServiceStack/wiki/SOAP-support) and -[Rabbit MQ](https://github.com/ServiceStack/ServiceStack/wiki/Rabbit-MQ), -[Redis MQ](https://github.com/ServiceStack/ServiceStack/wiki/Messaging-and-Redis) and +[CSV](https://docs.servicestack.net/csv-format.html), +[JSV](https://docs.servicestack.net/json-jsv-and-xml.html), +[ProtoBuf](https://docs.servicestack.net/protobuf-format.html), +[Wire](https://docs.servicestack.net/wire-format.html) and +[MsgPack](https://docs.servicestack.net/messagepack-format.html)) +as well as XSD/WSDL for [SOAP endpoints](https://docs.servicestack.net/soap-support.html) and +[Rabbit MQ](https://docs.servicestack.net/rabbit-mq.html), +[Redis MQ](https://docs.servicestack.net/messaging-and-redis.html) and [Amazon SQS](https://github.com/ServiceStack/ServiceStack.Aws#sqsmqserver) MQ hosts. Its design and simplicity focus offers an unparalleled suite of productivity features that can be declaratively enabled without code, from creating fully queryable Web API's with just a single Typed Request DTO with -[Auto Query](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) supporting +[Auto Query](https://docs.servicestack.net/autoquery.html) supporting [every major RDBMS](https://github.com/ServiceStack/ServiceStack.OrmLite#8-flavours-of-ormlite-is-on-nuget) to the built-in support for -[Auto Batched Requests](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Batched-Requests) -or effortlessly enabling rich [HTTP Caching](https://github.com/ServiceStack/ServiceStack/wiki/HTTP-Caching) and -[Encrypted Messaging](https://github.com/ServiceStack/ServiceStack/wiki/Encrypted-Messaging) -for all your existing services via [Plugins](https://github.com/ServiceStack/ServiceStack/wiki/Plugins). +[Auto Batched Requests](https://docs.servicestack.net/auto-batched-requests.html) +or effortlessly enabling rich [HTTP Caching](https://docs.servicestack.net/http-caching.html) and +[Encrypted Messaging](https://docs.servicestack.net/encrypted-messaging.html) +for all your existing services via [Plugins](https://docs.servicestack.net/plugins.html). Your same Services also serve as the Controller in ServiceStack's [Smart Razor Views](http://razor.servicestack.net/) reducing the effort to serve both [Web and Single Page Apps](https://github.com/ServiceStackApps/LiveDemos) as well as [Rich Desktop and Mobile Clients](https://github.com/ServiceStackApps/HelloMobile) that are able to deliver instant interactive -experiences using ServiceStack's real-time [Server Events](https://github.com/ServiceStack/ServiceStack/wiki/Server-Events). +experiences using ServiceStack's real-time [Server Events](https://docs.servicestack.net/server-events.html). ServiceStack Services also maximize productivity for consumers providing an -[instant end-to-end typed API without code-gen](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) enabling +[instant end-to-end typed API without code-gen](https://docs.servicestack.net/csharp-client.html) enabling the most productive development experience for developing .NET to .NET Web Services. -### [Generate Instant Typed APIs from within all Major IDEs!](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) +### [Generate Instant Typed APIs from within all Major IDEs!](https://docs.servicestack.net/add-servicestack-reference.html) ServiceStack now integrates with all Major IDE's used for creating the best native experiences on the most popular platforms to enable a highly productive dev workflow for consuming Web Services, making ServiceStack the ideal back-end choice for powering -rich, native iPhone and iPad Apps on iOS with Swift, Mobile and Tablet Apps on the Android platform with Java, OSX Desktop Appications -as well as targetting the most popular .NET PCL platforms including Xamarin.iOS, Xamarin.Android, Windows Store, WPF, WinForms and Silverlight: +rich, native iPhone and iPad Apps on iOS with Swift, Mobile and Tablet Apps on the Android platform with Java, OSX Desktop Applications +as well as targeting the most popular .NET PCL platforms including Xamarin.iOS, Xamarin.Android, Windows Store, WPF, WinForms and Silverlight: #### [VS.NET integration with ServiceStackVS](https://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) Providing instant Native Typed API's for -[C#](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference), -[F#](https://github.com/ServiceStack/ServiceStack/wiki/FSharp-Add-ServiceStack-Reference), -[VB.NET](https://github.com/ServiceStack/ServiceStack/wiki/VB.Net-Add-ServiceStack-Reference) -and [TypeScript](https://github.com/ServiceStack/ServiceStack/wiki/TypeScript-Add-ServiceStack-Reference) +[C#](https://docs.servicestack.net/csharp-add-servicestack-reference.html), +[TypeScript](https://docs.servicestack.net/typescript-add-servicestack-reference.html), +[F#](https://docs.servicestack.net/fsharp-add-servicestack-reference.html) and +[VB.NET](https://docs.servicestack.net/vbnet-add-servicestack-reference.html) directly in Visual Studio for the [most popular .NET platforms](https://github.com/ServiceStackApps/HelloMobile) including iOS and Android using [Xamarin.iOS](https://github.com/ServiceStackApps/HelloMobile#xamarinios-client) and [Xamarin.Android](https://github.com/ServiceStackApps/HelloMobile#xamarinandroid-client) on Windows. -#### [Xamarin Studio integration with ServiceStackXS](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference#xamarin-studio) +#### [Xamarin Studio integration with ServiceStackXS](https://docs.servicestack.net/csharp-add-servicestack-reference.html#xamarin-studio) -Providing [C# Native Types](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference) +Providing [C# Native Types](https://docs.servicestack.net/csharp-add-servicestack-reference.html) support for developing iOS and Android mobile Apps using [Xamarin.iOS](https://github.com/ServiceStackApps/HelloMobile#xamarinios-client) and [Xamarin.Android](https://github.com/ServiceStackApps/HelloMobile#xamarinandroid-client) with [Xamarin Studio](https://www.xamarin.com/studio) on OSX. The **ServiceStackXS** plugin also provides a rich web service development experience developing Client applications with -[Mono Develop on Linux](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference#xamarin-studio-for-linux) +[Mono Develop on Linux](https://docs.servicestack.net/csharp-add-servicestack-reference.html#xamarin-studio-for-linux) -#### [Xcode integration with ServiceStackXC Plugin](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference) +#### [Xcode integration with ServiceStackXC Plugin](https://docs.servicestack.net/swift-add-servicestack-reference.html) -Providing [an instant Native Typed API in Swift](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference) +Providing [an instant Native Typed API in Swift](https://docs.servicestack.net/swift-add-servicestack-reference.html) including generic Service Clients enabling a highly-productive workflow and effortless consumption of Web Services from native iOS and OSX Applications - directly from within Xcode! -#### [Android Studio integration with ServiceStackIDEA](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) +#### [Android Studio integration with ServiceStackIDEA](https://docs.servicestack.net/java-add-servicestack-reference.html) -Providing [an instant Native Typed API in Java](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) -and [Kotlin](https://github.com/ServiceStack/ServiceStack/wiki/Kotlin-Add-ServiceStack-Reference) -including idiomatic Java Generic Service Clients supporting Sync and Async Requests by levaraging Android's AsyncTasks to enable the creation of services-rich and responsive native Java or Kotlin Mobile Apps on the Android platform - directly from within Android Studio! +Providing [an instant Native Typed API in Java](https://docs.servicestack.net/java-add-servicestack-reference.html) +and [Kotlin](https://docs.servicestack.net/kotlin-add-servicestack-reference.html) +including idiomatic Java Generic Service Clients supporting Sync and Async Requests by leveraging Android's AsyncTasks to enable the creation of services-rich and responsive native Java or Kotlin Mobile Apps on the Android platform - directly from within Android Studio! -#### [IntelliJ integration with ServiceStackIDEA](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference#install-servicestack-idea-from-the-plugin-repository) +#### [IntelliJ integration with ServiceStackIDEA](https://docs.servicestack.net/java-add-servicestack-reference.html#install-servicestack-idea-from-the-plugin-repository) -The ServiceStack IDEA plugin is installable directly from IntelliJ's Plugin repository and enables seamless integration with IntelliJ Java Maven projects for genearting a Typed API to quickly and effortlessly consume remote ServiceStack Web Services from pure cross-platform Java or Kotlin Clients. +The ServiceStack IDEA plugin is installable directly from IntelliJ's Plugin repository and enables seamless integration with IntelliJ Java Maven projects for generating a Typed API to quickly and effortlessly consume remote ServiceStack Web Services from pure cross-platform Java or Kotlin Clients. #### [Eclipse integration with ServiceStackEclipse](https://github.com/ServiceStack/ServiceStack.Java/tree/master/src/ServiceStackEclipse#eclipse-integration-with-servicestack) -The unmatched productivity offered by [Java Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) is also available in the +The unmatched productivity offered by [Java Add ServiceStack Reference](https://docs.servicestack.net/java-add-servicestack-reference.html) is also available in the [ServiceStackEclipse IDE Plugin](https://github.com/ServiceStack/ServiceStack.Java/tree/master/src/ServiceStackEclipse#eclipse-integration-with-servicestack) that's installable from the [Eclipse MarketPlace](https://marketplace.eclipse.org/content/servicestackeclipse) to provide deep integration of Add ServiceStack Reference with Eclipse Java Maven Projects enabling Java Developers to effortlessly Add and Update the references of their evolving remote ServiceStack Web Services. -#### [ssutil.exe - Command line ServiceStack Reference tool](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference#ssutilexe---command-line-servicestack-reference-tool) +#### [servicestack-cli - Simple command-line utilities for ServiceStack](https://docs.servicestack.net/add-servicestack-reference.html#simple-command-line-utilities-for-servicestack) -In addition to our growing list of supported IDE's, the -[ssutil.exe](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference#ssutilexe---command-line-servicestack-reference-tool) -cross-platform command-line .NET .exe makes it easy for build servers, automated tasks and command-line runners of your +In addition to our growing list of supported IDE's, the [servicestack-cli](https://github.com/ServiceStack/servicestack-cli) +cross-platform command-line npm scripts makes it easy for build servers, automated tasks and command-line runners of your favorite text editors to easily Add and Update ServiceStack References! ## Simple Customer Database REST Services Example @@ -215,7 +215,7 @@ public class CustomerService : Service ``` -### [Calling the above REST Service from any C#/.NET Client](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) +### [Calling the above REST Service from any C#/.NET Client](https://docs.servicestack.net/csharp-add-servicestack-reference.html) > No code-gen required, can re-use above Server DTOs: @@ -245,24 +245,20 @@ client.Delete(new DeleteCustomer { Id = customer.Id }); all = client.Get(new GetCustomers()); // Count = 0 ``` -Same code also works with [PCL Clients in Xamarin iOS/Android, Windows Store Apps](https://github.com/ServiceStackApps/HelloMobile) +Same code also works with [Android, iOS, Xamarin.Forms, UWP and WPF clients](https://github.com/ServiceStackApps/HelloMobile). -> [F#](https://github.com/ServiceStack/ServiceStack/wiki/FSharp-Add-ServiceStack-Reference) and -[VB.NET](https://github.com/ServiceStack/ServiceStack/wiki/VB.Net-Add-ServiceStack-Reference) can re-use same -[.NET Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) and DTO's +> [F#](https://docs.servicestack.net/fsharp-add-servicestack-reference.html) and +[VB.NET](https://docs.servicestack.net/vbnet-add-servicestack-reference.html) can re-use same +[.NET Service Clients](https://docs.servicestack.net/csharp-client.html) and DTO's -### [Calling from TypeScript](https://github.com/ServiceStack/ServiceStack/wiki/TypeScript-Add-ServiceStack-Reference#ideal-typed-message-based-api) +### [Calling from TypeScript](https://docs.servicestack.net/typescript-add-servicestack-reference.html#ideal-typed-message-based-api) ```ts const client = new JsonServiceClient(baseUrl); - -client.get(new GetCustomers()) - .then(r => { - const results = r.results; - }); +const { results } = await client.get(new GetCustomers()); ``` -### [Calling from Swift](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference#jsonserviceclientswift) +### [Calling from Swift](https://docs.servicestack.net/swift-add-servicestack-reference.html#jsonserviceclientswift) ```swift let client = JsonServiceClient(baseUrl: BaseUri) @@ -273,7 +269,7 @@ client.getAsync(GetCustomers()) } ``` -### [Calling from Java](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference#jsonserviceclient-usage) +### [Calling from Java](https://docs.servicestack.net/java-add-servicestack-reference.html#jsonserviceclient-usage) ```java JsonServiceClient client = new JsonServiceClient(BaseUri); @@ -282,7 +278,7 @@ GetCustomersResponse response = client.get(new GetCustomers()); List results = response.results; ``` -### [Calling from Kotlin](https://github.com/ServiceStack/ServiceStack/wiki/Kotlin-Add-ServiceStack-Reference#jsonserviceclient-usage) +### [Calling from Kotlin](https://docs.servicestack.net/kotlin-add-servicestack-reference.html#jsonserviceclient-usage) ```kotlin val client = JsonServiceClient(BaseUri) @@ -291,40 +287,48 @@ val response = client.get(GetCustomers()) val results = response.results ``` -### [Calling from jQuery using TypeScript Defintions](https://github.com/ServiceStack/ServiceStack/wiki/TypeScript-Add-ServiceStack-Reference#typescript-interface-definitions) +### [Calling from Dart](https://docs.servicestack.net/dart-add-servicestack-reference) -```js -$.getJSON($.ss.createUrl("/customers", request), request, - function (r: dtos.GetCustomersResponse) { - alert(r.Results.length == 1); - }); +```dart +var client = new JsonServiceClient(BaseUri); + +var response = await client.get(GetCustomers()); +var results = client.results; ``` -### Calling from jQuery +### [Calling from jQuery using TypeScript Definitions](https://docs.servicestack.net/typescript-add-servicestack-reference.html#typescript-interface-definitions) ```js -$.getJSON(baseUri + "/customers", function(r) { - alert(r.Results.length == 1); +$.getJSON($.ss.createUrl("/customers", request), request, (r: GetCustomersResponse) => { + var results = r.results; }); ``` -### Calling the from [Dart JsonClient](https://github.com/mythz/DartJsonClient) +Using TypeScript Definitions with Angular HTTP Client: -```dart -var client = new JsonClient(baseUri); -client.customers() - .then((r) => alert(r.Results.length == 1)); +```ts +this.http.get(createUrl('/customers', request)).subscribe(r => { + this.results = r.results; +}); +``` + +### Calling from jQuery + +```js +$.getJSON(baseUri + "/customers", function(r) { + var results = r.results; +}); ``` That's all the application code required to create and consume a simple database-enabled REST Web Service! ## Getting Started - * [Start with the **Getting Started** section on the Wiki](https://github.com/ServiceStack/ServiceStack/wiki) - * [Example Apps and Demos](http://stackoverflow.com/questions/15862634/in-what-order-are-the-servicestack-examples-supposed-to-be-grokked/15869816#15869816) - * [Community resources](https://github.com/ServiceStack/ServiceStack/wiki/Community-Resources) + * [Start with the **Getting Started** section](https://docs.servicestack.net/create-your-first-webservice.html) + * [Example Apps and Demos](https://github.com/ServiceStackApps/LiveDemos) + * [Community resources](https://docs.servicestack.net/community-resources.html) -### [Release Notes](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md) +### [Release Notes](https://servicestack.net/release-notes) ## Download @@ -347,25 +351,27 @@ Alternative commercial licensing is also available, see https://servicestack.net ## Contributing -Contributors need to approve the [Contributor License Agreement](https://docs.google.com/forms/d/16Op0fmKaqYtxGL4sg7w_g-cXXyCoWjzppgkuqzOeKyk/viewform) before any code will be reviewed, see the [Contributing wiki](https://github.com/ServiceStack/ServiceStack/wiki/Contributing) for more details. All contributions must include tests verifying the desired behavior. +Contributors need to approve the [Contributor License Agreement](https://docs.google.com/forms/d/16Op0fmKaqYtxGL4sg7w_g-cXXyCoWjzppgkuqzOeKyk/viewform) before any code will be reviewed, see the [Contributing docs](https://docs.servicestack.net/contributing.html) for more details. All contributions must include tests verifying the desired behavior. ## OSS Libraries used ServiceStack includes source code of the great libraries below for some of its core functionality. Each library is released under its respective licence: - - [Mono](https://github.com/mono/mono) [(License)](https://github.com/mono/mono/blob/master/LICENSE) - - [Funq IOC](http://funq.codeplex.com) [(License)](http://funq.codeplex.com/license) - - [Fluent Validation](http://fluentvalidation.codeplex.com) [(License)](http://fluentvalidation.codeplex.com/license) - - [Mini Profiler](https://code.google.com/archive/p/mvc-mini-profiler) [(License)](http://www.apache.org/licenses/LICENSE-2.0) - - [Dapper](https://code.google.com/archive/p/dapper-dot-net) [(License)](http://www.apache.org/licenses/LICENSE-2.0) - - [TweetStation's OAuth library](https://github.com/migueldeicaza/TweetStation) [(License)](https://github.com/migueldeicaza/TweetStation/blob/master/LICENSE) - - [MarkdownSharp](https://code.google.com/archive/p/markdownsharp) [(License)](https://opensource.org/licenses/mit-license.php) - - [MarkdownDeep](https://github.com/toptensoftware/markdowndeep) [(License)](http://www.toptensoftware.com/markdowndeep/license) - - [HtmlCompressor](https://code.google.com/archive/p/htmlcompressor) [(License)](http://www.apache.org/licenses/LICENSE-2.0) - - [JSMin](https://github.com/douglascrockford/JSMin/blob/master/jsmin.c) [(License)](http://www.apache.org/licenses/LICENSE-2.0) - - [RecyclableMemoryStream](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream) [(License)](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream/blob/master/LICENSE) - - [ASP.NET MVC](https://github.com/aspnet/Mvc) [(License)](https://github.com/aspnet/Mvc/blob/dev/LICENSE.txt) + - [Mono](https://github.com/mono/mono) [(MIT License)](https://github.com/mono/mono/blob/master/LICENSE) + - [Funq IOC](http://funq.codeplex.com) [(MS-PL License)](https://opensource.org/licenses/MS-PL) + - [Fluent Validation](https://github.com/JeremySkinner/FluentValidation) [(Apache License 2.0)](https://github.com/JeremySkinner/FluentValidation/blob/master/License.txt) + - [Mini Profiler](https://github.com/MiniProfiler/dotnet) [(MIT License)](https://github.com/MiniProfiler/dotnet/blob/master/LICENSE.txt) + - [Dapper](https://github.com/StackExchange/Dapper) [(Apache License 2.0)](http://www.apache.org/licenses/LICENSE-2.0) + - [TweetStation's OAuth library](https://github.com/migueldeicaza/TweetStation) [(MIT License)](https://github.com/migueldeicaza/TweetStation/blob/master/LICENSE) + - [MarkdownSharp](https://code.google.com/archive/p/markdownsharp) [(MIT License)](https://opensource.org/licenses/mit-license.php) + - [MarkdownDeep](https://github.com/toptensoftware/markdowndeep) [(Apache License 2.0)](http://www.toptensoftware.com/markdowndeep/license) + - [HtmlCompressor](https://code.google.com/archive/p/htmlcompressor) [(Apache License 2.0)](http://www.apache.org/licenses/LICENSE-2.0) + - [JSMin](https://github.com/douglascrockford/JSMin/blob/master/jsmin.c) [(Apache License 2.0)](http://www.apache.org/licenses/LICENSE-2.0) + - [RecyclableMemoryStream](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream) [(MIT License)](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream/blob/master/LICENSE) + - [ASP.NET MVC](https://github.com/aspnet/Mvc) [(Apache License 2.0)](https://github.com/aspnet/Mvc/blob/release/2.2/LICENSE.txt) + - [CoreFX](https://github.com/dotnet/corefx) [(MIT License)](https://github.com/dotnet/corefx/blob/master/LICENSE.TXT) + - [Nito.AsyncEx](https://github.com/StephenCleary/AsyncEx) [(MIT License)](https://github.com/StephenCleary/AsyncEx/blob/master/LICENSE) ## Find out More @@ -379,10 +385,11 @@ Follow [@ServiceStack](https://twitter.com/ServiceStack) and - [mythz](https://github.com/mythz) (Demis Bellot) - [layoric](https://github.com/layoric) (Darren Reid) / [@layoric](https://twitter.com/layoric) - [xplicit](https://github.com/xplicit) (Sergey Zhukov) / [@quantumcalc](https://twitter.com/quantumcalc) - - [arxisos](https://github.com/arxisos) (Steffen Müller) / [@arxisos](https://twitter.com/arxisos) - [desunit](https://github.com/desunit) (Sergey Bogdanov) / [@desunit](https://twitter.com/desunit) + - [arxisos](https://github.com/arxisos) (Steffen Müller) / [@arxisos](https://twitter.com/arxisos) ## Contributors + A big thanks to GitHub and all of ServiceStack's contributors: - [bman654](https://github.com/bman654) (Brandon Wallace) @@ -658,7 +665,7 @@ A big thanks to GitHub and all of ServiceStack's contributors: - [kaza](https://github.com/kaza) - [mishfit](https://github.com/mishfit) - [rfvgyhn](https://github.com/rfvgyhn) (Chris) - - [caioproiete](https://github.com/caioproiete) (Caio Proiete) + - [augustoproiete](https://github.com/augustoproiete) (C. Augusto Proiete) - [sjuxax](https://github.com/sjuxax) (Jeff Cook) - [madaleno](https://github.com/madaleno) (Luis Madaleno) - [yavosh](https://github.com/yavosh) (Yavor Shahpasov) @@ -693,5 +700,5 @@ A big thanks to GitHub and all of ServiceStack's contributors: Similar Open source .NET projects for developing or accessing web services include: * [Nancy Fx](http://nancyfx.org) - A Sinatra-inspired lightweight Web Framework for .NET: - * [Fubu MVC](http://mvc.fubu-project.org) - A "Front Controller" pattern-style MVC framework designed for use in web applications built on ASP.NET: + * [Fubu MVC](https://fubumvc.github.io/) - A "Front Controller" pattern-style MVC framework designed for use in web applications built on ASP.NET: * [Rest Sharp](http://restsharp.org) - An open source REST client for .NET diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..8910a154ee1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report security issues to https://servicestack.net/#contact diff --git a/build.cmd b/build.cmd deleted file mode 100644 index 2505a1f9785..00000000000 --- a/build.cmd +++ /dev/null @@ -1,15 +0,0 @@ -@echo off - -set target=%1 -if "%target%" == "" ( - set target=UnitTests -) - -if "%target%" == "NuGetPack" ( - if "%BUILD_NUMBER%" == "" ( - echo BUILD_NUMBER environment variable is not set. - exit; - ) -) - -%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild Build\Build.proj /target:%target% /v:M /fl /flp:LogFile=msbuild.log;Verbosity=Normal /nr:false \ No newline at end of file diff --git a/build/7za.exe b/build/7za.exe deleted file mode 100644 index 06e8b434f73..00000000000 Binary files a/build/7za.exe and /dev/null differ diff --git a/build/appsettings.license.txt b/build/appsettings.license.txt deleted file mode 100644 index 1e498b17527..00000000000 --- a/build/appsettings.license.txt +++ /dev/null @@ -1 +0,0 @@ -1001-e1JlZjoxMDAxLE5hbWU6VGVzdCBCdXNpbmVzcyxUeXBlOkJ1c2luZXNzLEhhc2g6UHVNTVRPclhvT2ZIbjQ5MG5LZE1mUTd5RUMzQnBucTFEbTE3TDczVEF4QUNMT1FhNXJMOWkzVjFGL2ZkVTE3Q2pDNENqTkQyUktRWmhvUVBhYTBiekJGUUZ3ZE5aZHFDYm9hL3lydGlwUHI5K1JsaTBYbzNsUC85cjVJNHE5QVhldDN6QkE4aTlvdldrdTgyTk1relY2eis2dFFqTThYN2lmc0JveHgycFdjPSxFeHBpcnk6MjAxMy0wMS0wMX0= \ No newline at end of file diff --git a/build/build-common-core.proj b/build/build-common-core.proj new file mode 100644 index 00000000000..7904c64b0a5 --- /dev/null +++ b/build/build-common-core.proj @@ -0,0 +1,118 @@ + + + + + + 6 + 0 + $(BUILD_NUMBER) + + + + $(MSBuildProjectDirectory)/.. + $(BuildSolutionDir)/src + Release + $(BuildSolutionDir)/NuGet/ + $(MajorVersion).$(MinorVersion).$(PatchVersion) + + + + + BeforeBuildSolutions; + BuildSolutions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <Version>[^<]* + <Version>$(PackageVersion) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/build-common.proj b/build/build-common.proj new file mode 100644 index 00000000000..7441da7383d --- /dev/null +++ b/build/build-common.proj @@ -0,0 +1,115 @@ + + + + + + 6 + 0 + $(BUILD_NUMBER) + + + + $(MSBuildProjectDirectory)/.. + $(BuildSolutionDir)/src + Release + $(BuildSolutionDir)/NuGet/ + $(MajorVersion).$(MinorVersion).$(PatchVersion) + + + + + BeforeBuildSolutions; + BuildSolutions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <Version>[^<]* + <Version>$(PackageVersion) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/build-core.proj b/build/build-core.proj new file mode 100644 index 00000000000..df08fbea29d --- /dev/null +++ b/build/build-core.proj @@ -0,0 +1,175 @@ + + + + + + 6 + 0 + $(BUILD_NUMBER) + + + + $(MSBuildProjectDirectory)/.. + $(BuildSolutionDir)/src + Release + $(BuildSolutionDir)/NuGet/ + $(MajorVersion).$(MinorVersion).$(PatchVersion) + + + + + BeforeBuildSolutions; + BuildSolutions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <Version>[^<]* + <Version>$(PackageVersion) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/build-core.sh b/build/build-core.sh deleted file mode 100755 index 54dc5617152..00000000000 --- a/build/build-core.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -if [ -z "$MajorVersion" ]; then - MajorVersion=1 -fi -if [ -z "$MinorVersion" ]; then - MinorVersion=0 -fi -if [ -z "$PatchVersion" ]; then - PatchVersion=$BUILD_NUMBER -fi -if [ -z "$RELEASE" ]; then - UnstableTag="-unstable" -fi - -Version=$MajorVersion.$MinorVersion.$PatchVersion.0 -EnvVersion=$MajorVersion.$MinorVersion$PatchVersion -PackageVersion=$MajorVersion.$MinorVersion.$PatchVersion$UnstableTag - -echo replace AssemblyVersion -find ./src -type f -name "AssemblyInfo.cs" -exec sed -i "s/AssemblyVersion(\"[^\"]\+\")/AssemblyVersion(\"1.0.0.0\")/g" {} + -echo replace AssemblyFileVersion -find ./src -type f -name "AssemblyInfo.cs" -exec sed -i "s/AssemblyFileVersion(\"[^\"]\+\")/AssemblyFileVersion(\"${Version}\")/g" {} + - -echo replace project.json -sed -i "s/\"version\": \"[^\"]\+\"/\"version\": \"${Version}\"/g" ./src/ServiceStack.NetCore/ServiceStack.Text/project.json -sed -i "s/\"version\": \"[^\"]\+\"/\"version\": \"${Version}\"/g" ./src/ServiceStack.NetCore/ServiceStack.Client/project.json -sed -i "s/\"version\": \"[^\"]\+\"/\"version\": \"${Version}\"/g" ./src/ServiceStack.NetCore/ServiceStack.Interfaces/project.json -sed -i "s/\"version\": \"[^\"]\+\"/\"version\": \"${Version}\"/g" ./src/ServiceStack.NetCore/ServiceStack.Common/project.json - -echo replace package -find ./NuGet.Core -type f -name "*.nuspec" -exec sed -i "s/[^<]\+/${PackageVersion}/g" {} + -find ./NuGet.Core -type f -name "*.nuspec" -exec sed -i "s/\"ServiceStack.Text.Core\" version=\"[^\"]\+\"/\"ServiceStack.Text.Core\" version=\"\[${PackageVersion}, \)\"/g" {} + -find ./NuGet.Core -type f -name "*.nuspec" -exec sed -i "s/\"ServiceStack.Interfaces.Core\" version=\"[^\"]\+\"/\"ServiceStack.Interfaces.Core\" version=\"\[${PackageVersion}, \)\"/g" {} + - - -#restore packages -#(cd ./src/ServiceStack.NetCore && dotnet restore) -#(cd ./tests/ServiceStack.Common.NetCore/ServiceStack.Common.Tests && dotnet restore) - -#execute tests -#(cd ./tests/ServiceStack.Text.Tests.NetCore/ServiceStack.Text.Tests && dotnet run -c Release) - -#nuget pack -#(cd ./NuGet.Core && ./nuget.exe pack ServiceStack.Text.Core/servicestack.text.core.nuspec -symbols) diff --git a/build/build-pcl.proj b/build/build-pcl.proj deleted file mode 100644 index 25b6b4244b0..00000000000 --- a/build/build-pcl.proj +++ /dev/null @@ -1,187 +0,0 @@ - - - - - 4 - 5 - $(BUILD_NUMBER) - - - - $(MSBuildProjectDirectory)/.. - $(BuildSolutionDir)/src - Release - /noshadow - $(SrcDir)/.nuget/nuget.exe - $(BuildSolutionDir)/NuGet.Pcl/ - $(MajorVersion).$(MinorVersion).$(PatchVersion).0 - -unstable - $(MajorVersion).$(MinorVersion).$(PatchVersion)$(UnstableTag) - $(MajorVersion).$(MinorVersion)$(PatchVersion) - - - - - BuildSolutions - - - - - - - - - - - - - - - - - - - - - - - - - - - - AssemblyFileVersion\(\"\d+\.\d+\.\d+\.\d+\"\) - AssemblyFileVersion("$(Version)") - - - - - AssemblyVersion\(\"\d+\.\d+\.\d+\.\d+\"\) - AssemblyVersion("4.0.0.0") - - - - - version="4\.5[^"]*" - version="$(PackageVersion)" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/build-remote.proj b/build/build-remote.proj deleted file mode 100644 index 01e6b2eccf0..00000000000 --- a/build/build-remote.proj +++ /dev/null @@ -1,223 +0,0 @@ - - - - - 3 - 9 - $(BUILD_NUMBER) - - - - $(MSBuildProjectDirectory)/.. - $(BuildSolutionDir)/src - Release - /noshadow - $(BuildSolutionDir)/src/.nuget/nuget.exe - $(BuildSolutionDir)/NuGet/ - $(MSBuildProjectDirectory) - $(MajorVersion).$(MinorVersion).$(PatchVersion).0 - -unstable - $(MajorVersion).$(MinorVersion).$(PatchVersion)$(UnstableTag) - $(MajorVersion).$(MinorVersion)$(PatchVersion) - - - - - BuildSolutions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \d+\.\d+\.\d+\.\d+ - $(Version) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/build-sn.proj b/build/build-sn.proj deleted file mode 100644 index 19b40a1f651..00000000000 --- a/build/build-sn.proj +++ /dev/null @@ -1,219 +0,0 @@ - - - - - 4 - 5 - $(BUILD_NUMBER) - - - - $(MSBuildProjectDirectory)/.. - $(BuildSolutionDir)/src - Signed - /noshadow - $(SrcDir)/.nuget/nuget.exe - $(BuildSolutionDir)/NuGet.Signed/ - $(MajorVersion).$(MinorVersion).$(PatchVersion).0 - -unstable - $(MajorVersion).$(MinorVersion).$(PatchVersion)$(UnstableTag) - $(MajorVersion).$(MinorVersion)$(PatchVersion) - - - - - BuildSolutions - - - - - - - - - - - - - - - - - - - - - - - - - - AssemblyFileVersion\(\"\d+\.\d+\.\d+\.\d+\"\) - AssemblyFileVersion("$(Version)") - - - - - AssemblyVersion\(\"\d+\.\d+\.\d+\.\d+\"\) - AssemblyVersion("4.0.0.0") - - - - - version="4\.5[^"]*" - version="$(PackageVersion)" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/build.bat b/build/build.bat index 07cc97dc034..7cd0981c96d 100644 --- a/build/build.bat +++ b/build/build.bat @@ -1,8 +1,4 @@ -SET MSBUILD=C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe - -%MSBUILD% build.proj /target:TeamCityBuild;NuGetPack /property:Configuration=Release;RELEASE=true;PatchVersion=0 -REM %MSBUILD% build-sn.proj /target:TeamCityBuild;NuGetPack /property:Configuration=Signed;RELEASE=true;PatchVersion=0 -REM %MSBUILD% build-pcl.proj /target:TeamCityBuild;NuGetPack /property:Configuration=Release;RELEASE=true;PatchVersion=0 - -REM Debug Task -REM C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe /t:rebuild /debug C:\src\ServiceStack\tests\RazorRockstars.BuildTask\RazorRockstars.BuildTask.csproj +for /f "usebackq tokens=*" %%i in (`vswhere.exe -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe`) do ( + SET MSBUILD="%%i" +) +%MSBUILD% build.proj /property:Configuration=Release;MinorVersion=8;PatchVersion=1 diff --git a/build/build.proj b/build/build.proj index 365417a226f..f11eb49847d 100644 --- a/build/build.proj +++ b/build/build.proj @@ -1,9 +1,11 @@ - + + - 4 - 5 + 6 + 0 $(BUILD_NUMBER) @@ -11,475 +13,216 @@ $(MSBuildProjectDirectory)/.. $(BuildSolutionDir)/src Release - /noshadow - $(SrcDir)/.nuget/nuget.exe $(BuildSolutionDir)/NuGet/ - $(MajorVersion).$(MinorVersion).$(PatchVersion).0 - -unstable - $(MajorVersion).$(MinorVersion).$(PatchVersion)$(UnstableTag) - $(MajorVersion).$(MinorVersion)$(PatchVersion) + $(MajorVersion).$(MinorVersion).$(PatchVersion) + BeforeBuildSolutions; BuildSolutions - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + - - AssemblyFileVersion\(\"\d+\.\d+\.\d+\.\d+\"\) - AssemblyFileVersion("$(Version)") - - - AssemblyVersion\(\"\d+\.\d+\.\d+\.\d+\"\) - AssemblyVersion("$(Version)") - - - key="servicestack:license".* - key="servicestack:license" value="$([System.IO.File]::ReadAllText($(MSBuildProjectDirectory)/appsettings.license.txt))" /> - - - - version="4\.0(\.\d+)?" - version="$(PackageVersion)" + + <Version>[^<]* + <Version>$(PackageVersion) - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - + + - - + + + - - - - - - + + - + + - + + - - + + + + - - - - - - - - - - - - - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - + + - - - - + + - + + - + + - - + + - + + - + + + + - - - - - - - - - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - - - - - - - - - - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> + - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - - - - + + + + + + - - - - - - - - - - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + Targets="Build;Pack" + Properties="Configuration=$(Configuration)" /> - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + + diff --git a/build/build.sh b/build/build.sh deleted file mode 100755 index 23f055432b6..00000000000 --- a/build/build.sh +++ /dev/null @@ -1,170 +0,0 @@ -#!/bin/bash - -MODO=Debug -LIB_DIR=lib -MONO_DIR=lib -#MODO=Release - -CURRENT_DIR=`pwd` -cd ../.. - -function makeMonoDir { - echo "$1/$MONO_DIR" - if [ ! -d "$1/$MONO_DIR" ] - then - mkdir -p "$1/$MONO_DIR"/tests - fi -} - -if [ ! -d "$LIB_DIR" ] -then - mkdir "$LIB_DIR" -fi - -function buildComponentAndCopyToServiceStack { - xbuild /p:Configuration="$MODO" "$1"/src/"$2"/"$2".csproj - cp "$1"/src/"$2"/bin/"$MODO"/"$2".dll "$LIB_DIR" - cp "$LIB_DIR"/"$2".dll ServiceStack/"$MONO_DIR" -} - -function buildComponent { - xbuild /p:Configuration="$MODO" "$1"/src/"$2"/"$2".csproj - cp "$1"/src/"$2"/bin/"$MODO"/"$2".dll "$LIB_DIR" -} - -function buildTestComponent { - xbuild /p:Configuration="$MODO" "$1"/tests/"$2"/"$2".csproj - cp "$1"/tests/"$2"/bin/"$MODO"/"$2".dll "$LIB_DIR" -} - -function buildServiceStackBenchmarks { - xbuild /p:Configuration="$MODO" "$1"/src/"$2"/"$3"/"$3".csproj - cp "$1"/src/"$2"/"$3"/bin/"$MODO"/"$3".dll "$LIB_DIR" -} - -makeMonoDir ServiceStack -makeMonoDir ServiceStack.OrmLite -makeMonoDir ServiceStack.Redis -makeMonoDir ServiceStack.Text - - -buildComponentAndCopyToServiceStack ServiceStack.Text ServiceStack.Text -cp "$LIB_DIR"/ServiceStack.Text.dll ServiceStack.OrmLite/"$MONO_DIR" -cp "$LIB_DIR"/ServiceStack.Text.dll ServiceStack.Redis/"$MONO_DIR" -cp "$LIB_DIR"/ServiceStack.Text.dll ServiceStack.Redis/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Text.dll ServiceStack.Text/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Text.dll ServiceStack.Logging/"$MONO_DIR" - -buildComponentAndCopyToServiceStack ServiceStack ServiceStack.Interfaces -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.OrmLite/"$MONO_DIR" -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.Redis/"$MONO_DIR" -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.Redis/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.Text/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.Logging/"$MONO_DIR" - -buildComponentAndCopyToServiceStack ServiceStack ServiceStack.Common -cp "$LIB_DIR"/ServiceStack.Common.dll ServiceStack.OrmLite/"$MONO_DIR" -cp "$LIB_DIR"/ServiceStack.Common.dll ServiceStack.Redis/"$MONO_DIR" -cp "$LIB_DIR"/ServiceStack.Common.dll ServiceStack.Redis/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Common.dll ServiceStack.Text/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/ServiceStack.Common.dll ServiceStack.Logging/"$MONO_DIR" - -buildComponent ServiceStack ServiceStack -cp "$LIB_DIR"/ServiceStack.dll ServiceStack.Redis/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.dll ServiceStack.Text/"$MONO_DIR"/tests - -buildComponentAndCopyToServiceStack ServiceStack.OrmLite ServiceStack.OrmLite -buildComponentAndCopyToServiceStack ServiceStack.OrmLite ServiceStack.OrmLite.Sqlite -buildComponentAndCopyToServiceStack ServiceStack.OrmLite ServiceStack.OrmLite.SqlServer -buildComponent ServiceStack.OrmLite ServiceStack.OrmLite.MySql -buildComponent ServiceStack.OrmLite ServiceStack.OrmLite.PostgreSQL -buildComponent ServiceStack.OrmLite ServiceStack.OrmLite.Firebird -buildComponent ServiceStack.OrmLite ServiceStack.OrmLite.Oracle - -cp "$LIB_DIR"/ServiceStack.OrmLite.dll ServiceStack.Text/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.OrmLite.SqlServer.dll ServiceStack.Text/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.OrmLite.Sqlite.dll ServiceStack.Text/"$MONO_DIR"/tests - -#ServiceStack again -buildComponent ServiceStack ServiceStack.Authentication.OpenId -buildComponent ServiceStack ServiceStack.Plugins.MsgPack -buildComponent ServiceStack ServiceStack.ServiceInterface -buildComponent ServiceStack ServiceStack.Plugins.ProtoBuf -buildComponent ServiceStack ServiceStack.FluentValidation.Mvc3 -buildComponent ServiceStack ServiceStack.Razor2 -cp "$LIB_DIR"/ServiceStack.Razor2.dll ServiceStack.Redis/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/ServiceStack.ServiceInterface.dll ServiceStack.Redis/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/ServiceStack.ServiceInterface.dll ServiceStack.Text/"$MONO_DIR"/tests/ - - -buildComponentAndCopyToServiceStack ServiceStack.Redis ServiceStack.Redis -cp "$LIB_DIR"/ServiceStack.Redis.dll ServiceStack.Redis/"$LIB_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Redis.dll ServiceStack.Text/"$LIB_DIR"/tests - -#ServiceStack.Benchmarks -cp "$LIB_DIR"/ServiceStack.dll ServiceStack.Benchmarks/lib -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.Benchmarks/lib - -cp "$LIB_DIR"/ServiceStack.Text.dll ServiceStack.Benchmarks/src/Northwind.Benchmarks/Lib -cp "$LIB_DIR"/ServiceStack.Interfaces.dll ServiceStack.Benchmarks/src/Northwind.Benchmarks/Lib - -buildServiceStackBenchmarks ServiceStack.Benchmarks Northwind.Benchmarks Northwind.Common -buildServiceStackBenchmarks ServiceStack.Benchmarks Northwind.Benchmarks Northwind.Perf -buildServiceStackBenchmarks ServiceStack.Benchmarks Northwind.Benchmarks Northwind.Benchmarks -buildServiceStackBenchmarks ServiceStack.Benchmarks Northwind.Benchmarks Northwind.Benchmarks.Console - -cp "$LIB_DIR"/Northwind.Common.dll ServiceStack/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/Northwind.Common.dll ServiceStack.OrmLite/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/Northwind.Common.dll ServiceStack.Redis/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/Northwind.Common.dll ServiceStack.Text/"$MONO_DIR"/tests/ -cp "$LIB_DIR"/Northwind.Perf.dll ServiceStack.OrmLite/"$MONO_DIR"/tests/ - - -buildTestComponent ServiceStack ServiceStack.Common.Tests -cp "$LIB_DIR"/ServiceStack.Common.Tests.dll ServiceStack.OrmLite/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Common.Tests.dll ServiceStack.Redis/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Common.Tests.dll ServiceStack.Text/"$MONO_DIR"/tests -buildTestComponent ServiceStack ServiceStack.Messaging.Tests -cp "$LIB_DIR"/ServiceStack.Messaging.Tests.dll ServiceStack.Redis/"$MONO_DIR"/tests -cp "$LIB_DIR"/ServiceStack.Messaging.Tests.dll ServiceStack.Text/"$MONO_DIR"/tests - - -#ServiceStack.RazorHostTests : xbuild can not build it, but monodevelop does it! - -#xbuild ServiceStack/tests/ServiceStack.RazorHostTests/ServiceStack.RazorHostTests.csproj - -#Imported project: -#"/usr/local/lib/mono/xbuild/Microsoft/VisualStudio/v10.0/WebApplications/Microsoft.WebApplication.targets" does not exist. -# there is v9.0 - -#ServiceStack.RazorNancyTests : xbuild can not build it, but monodevelop does it! -#xbuild ServiceStack/tests/ServiceStack.RazorNancyTests/ServiceStack.RazorNancyTests.csproj - -buildTestComponent ServiceStack ServiceStack.ServiceHost.Tests -buildTestComponent ServiceStack ServiceStack.ServiceModel.Tests -#ServiceStack.WebHost.Endpoints.Tests: warning as error -buildTestComponent ServiceStack ServiceStack.WebHost.Endpoints.Tests -#ServiceStack.WebHost.IntegrationTests -# execute once : -#sudo ln -s /usr/local/lib/mono/xbuild/Microsoft/VisualStudio/v9.0 /usr/local/lib/mono/xbuild/Microsoft/VisualStudio/v10.0 -buildTestComponent ServiceStack ServiceStack.WebHost.IntegrationTests -cp ServiceStack/tests/ServiceStack.WebHost.IntegrationTests/bin/ServiceStack.WebHost.IntegrationTests.dll "$LIB_DIR" - - -buildTestComponent ServiceStack.Redis ServiceStack.Redis.Tests -buildTestComponent ServiceStack.Text ServiceStack.Text.Tests -#ServiceStack.Text.Tests // comment public void #Can_Serialize_User_OAuthSession_list() and public void #Doesnt_serialize_TypeInfo_when_set() - - -#ServiceStack.Logging.EventLog - -#fail: ../../src//.nuget/nuget.targets: Project file could not be imported -#use monodevelop -#xbuild ServiceStack.Logging/src/ServiceStack.Logging.EventLog/ServiceStack.Logging.EventLog.csproj - -#ServiceStack.Logging.Log4Net -#fail: ../../src//.nuget/nuget.targets: Project file could not be imported -#use monodevelop -#xbuild #ServiceStack.Logging/src/ServiceStack.Logging.Log4Net/ServiceStack.Logging.Log4Net.csproj - -cd "$CURRENT_DIR" diff --git a/build/codegen-projs.js b/build/codegen-projs.js deleted file mode 100644 index bae82dc0a08..00000000000 --- a/build/codegen-projs.js +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) Service Stack LLC. All Rights Reserved. -// License: https://raw.github.com/ServiceStack/ServiceStack/master/license.txt - - -var fs = require('fs'); -var path = require('path'); -var sax = require("sax"); - -var log = console.log; -log("Generating .Signed.csprojs..."); - -function stripBOM(content) { - if (content.charCodeAt(0) === 0xFEFF) { - content = content.slice(1); - } - return content; -} - -String.prototype.lines = function() { - return this.replace(/\r/g, '').split('\n'); -}; - - -var SIGN_PROJS = [ - '../../ServiceStack.Text/src/ServiceStack.Text/ServiceStack.Text.csproj', - '../../ServiceStack.Redis/src/ServiceStack.Redis/ServiceStack.Redis.csproj', - '../../ServiceStack.OrmLite/src/ServiceStack.OrmLite/ServiceStack.OrmLite.csproj', - '../../ServiceStack.OrmLite/src/ServiceStack.OrmLite.SqlServer/ServiceStack.OrmLite.SqlServer.csproj', - '../../ServiceStack.OrmLite/src/ServiceStack.OrmLite.SqlServer.Converters/ServiceStack.OrmLite.SqlServer.Converters.csproj', - '../../ServiceStack.OrmLite/src/ServiceStack.OrmLite.Oracle/ServiceStack.OrmLite.Oracle.csproj', - '../../ServiceStack.OrmLite/src/ServiceStack.OrmLite.Sqlite.Windows/ServiceStack.OrmLite.Sqlite.Windows.csproj', - '../../ServiceStack.OrmLite/src/ServiceStack.OrmLite.MySql/ServiceStack.OrmLite.MySql.csproj', - '../src/ServiceStack.Common/ServiceStack.Common.csproj', - '../src/ServiceStack.Client/ServiceStack.Client.csproj', - '../src/ServiceStack.Server/ServiceStack.Server.csproj', - '../src/ServiceStack.Razor/ServiceStack.Razor.csproj', - '../src/ServiceStack.ProtoBuf/ServiceStack.ProtoBuf.csproj', - '../src/ServiceStack.Api.Swagger/ServiceStack.Api.Swagger.csproj', - '../src/ServiceStack.Authentication.OAuth2/ServiceStack.Authentication.OAuth2.csproj', - '../src/ServiceStack.Mvc/ServiceStack.Mvc.csproj', - '../../Admin/src/ServiceStack.Admin/ServiceStack.Admin.csproj', - '../../ServiceStack.Aws/src/ServiceStack.Aws/ServiceStack.Aws.csproj', - '../src/ServiceStack/ServiceStack.csproj' -]; -var SIGN_REPLACE_TEXTS = { - '..\\..\\lib\\ServiceStack.Text.dll': '..\\..\\lib\\signed\\ServiceStack.Text.dll', - '..\\..\\lib\\ServiceStack.Common.dll': '..\\..\\lib\\signed\\ServiceStack.Common.dll', - '..\\..\\lib\\ServiceStack.Client.dll': '..\\..\\lib\\signed\\ServiceStack.Client.dll', - '..\\..\\lib\\ServiceStack.Redis.dll': '..\\..\\lib\\signed\\ServiceStack.Redis.dll', - '..\\..\\lib\\ServiceStack.OrmLite.dll': '..\\..\\lib\\signed\\ServiceStack.OrmLite.dll', - '..\\..\\lib\\ServiceStack.dll': '..\\..\\lib\\signed\\ServiceStack.dll', - '..\\..\\lib\\ServiceStack.Server.dll': '..\\..\\lib\\signed\\ServiceStack.Server.dll', - '..\\..\\lib\\net45\\ServiceStack.OrmLite.dll': '..\\..\\lib\\net45\\signed\\ServiceStack.OrmLite.dll', - '..\\..\\lib\\ServiceStack.OrmLite.SqlServer.dll': '..\\..\\lib\\signed\\ServiceStack.OrmLite.SqlServer.dll', - '': '', - '': '', - '': '', - '': '' -}; - -var injectSignedElements = [ - { - PropertyGroup: { - SignAssembly: "true", - } - }, - { - PropertyGroup: { - AssemblyOriginatorKeyFile: "servicestack-sn.pfx" - } - } -]; - -var readTextFile = function (path) { - return stripBOM(fs.readFileSync(path, { encoding: 'UTF-8' })); -}; - -var mergeElements = function (xml, els) { - els.forEach(function(elSeek) { - Object.keys(elSeek).forEach(function(tag) { - var tagToMatch = tag.toUpperCase(); - - var strict = false; - var parser = sax.parser(strict); - - var matches = []; - var open = { line: 0, coloumn: 0, startTagPosition: 0 }; - - parser.onopentag = function (el) { - if (el.name == tagToMatch) { - log("found <" + tag + "> at: ", this.line + ":" + this.column); - open = { line: this.line, column: this.column, startTagPosition: this.startTagPosition }; - } - }; - parser.onclosetag = function (name) { - if (name == tagToMatch) { - log("found at: ", this.line + ":" + this.column); - matches.push({ start: open, end: { line: this.line, column: this.column, startTagPosition: this.startTagPosition } }); - } - }; - - parser.write(xml); - - log("results for " + tag); - log(matches); - - var props = elSeek[tag]; - var out = []; - var lastPos = 0; - var found = false; - - matches.forEach(function(match) { - var startPos = match.start.startTagPosition + match.start.column; - var endPos = match.end.startTagPosition - 1; - - out.push(xml.substring(lastPos, startPos)); - - var fragment = xml.substring(startPos, endPos); - - if (!found) { - var missing = []; - Object.keys(props).forEach(function (elName) { - var elValue = props[elName]; - var seekTag = "<" + elName + ">"; - var seekEndTag = ""; - var injectXml = seekTag + elValue + seekEndTag; - - var startPos; - if ((startPos = fragment.indexOf(seekTag)) >= 0) { - var endPos = fragment.indexOf(seekEndTag) + seekEndTag.length; - if (endPos == -1) - throw "Couldn't find matching end tag: " + seekEndTag; - - fragment = fragment.substring(0, startPos) - + injectXml - + fragment.substring(endPos); - - found = true; - } else { - missing.push(injectXml); - } - }); - - //If one was found, add the missing at the end fragment - if (found) { - missing.forEach(function(injectXml) { - fragment += " " + injectXml + "\n"; - }); - fragment += " "; - } - } - - out.push(fragment); - - lastPos = endPos; - }); - - //If we can't merge, append - if (!found) { - //Close open end tag first, then open new tag: - out.push("\n "); - out.push("<" + tag + ">\n"); - Object.keys(props).forEach(function (elName) { - var injectXml = " <" + elName + ">" + props[elName] + "\n"; - out.push(injectXml); - }); - //remaining fragment starts with closing tag - } - - out.push(" "); - out.push(xml.substring(lastPos)); - - xml = out.join(''); - }); - }); - - return xml; -}; - -SIGN_PROJS.forEach(function(proj) { - log("file: " + proj); - var xml = readTextFile(proj); - log(xml); - - var transformedXml = mergeElements(xml, injectSignedElements); - - Object.keys(SIGN_REPLACE_TEXTS).forEach(function (find) { - log("replacing: " + find + ", with: " + SIGN_REPLACE_TEXTS[find]); - transformedXml = transformedXml.replace(find, SIGN_REPLACE_TEXTS[find]); - }); - - var signedProjPath = path.join(path.dirname(proj), path.basename(proj).replace(".csproj", ".Signed.csproj")); - log("writing transformedXml to: " + signedProjPath); - log(transformedXml); - - fs.writeFileSync(signedProjPath, transformedXml); -}); - - -log("Generating Custom build .csprojs..."); - -var CUSTOM_TEMPLATES = [{ - Code: 'PCL', - Path: '../src/Templates/PclTemplate.csproj', - ProjectGuid: '{BF5EEDF0-594C-4660-AFF5-AF3423F3602D}', - RootNamespace: 'PclTemplate', - AssemblyName: 'PclTemplate', -}, -{ - Code: 'SL5', - Path: '../src/Templates/SilverlightTemplate.csproj', - ProjectGuid: '{12B8CB9F-E397-4B5F-89AF-B6998296BFE6}', - RootNamespace: 'SilverlightTemplate', - AssemblyName: 'SilverlightTemplate', -} -/*,{ - Code: 'Android', - Path: '../src/Templates/AndroidTemplate.csproj', - ProjectGuid: '{BEA92E9F-00B1-4923-BD81-7F3A9CA24408}', - RootNamespace: 'AndroidTemplate', - AssemblyName: 'AndroidTemplate', -}, -{ - Code: 'AndroidIndie', - Path: '../src/Templates/AndroidIndieTemplate.csproj', - ProjectGuid: '{BEA92E9F-00B1-4923-BD81-7F3A9CA24408}', - RootNamespace: 'AndroidIndieTemplate', - AssemblyName: 'AndroidIndieTemplate', -}*/ -]; - -var CUSTOM_PROJS = [ -//{ -// Path: '../src/ServiceStack.Interfaces/ServiceStack.Interfaces.csproj', -// ReplaceElements: { -// ProjectGuid: '{42E1C8C0-A163-44CC-92B1-8F416F2C0B01}', -// RootNamespace: 'ServiceStack', -// AssemblyName: 'ServiceStack.Interfaces', -// }, -// ReplaceTemplate: function (code, tmpl) { -// var replaceTexts = { -// '11.0': '10.0', -// 'v4.5': 'v4.0', -// 'Profile7': 'Profile136' -// }; -// if (code == 'PCL') { -// for (var needle in replaceTexts) { -// var replaceText = replaceTexts[needle]; -// tmpl = tmpl.replace(needle, replaceText); -// } -// } -// return tmpl; -// } -//}, -{ - Path: '../../ServiceStack.Text/src/ServiceStack.Text/ServiceStack.Text.csproj', - ReplaceElements: { - ProjectGuid: '{579B3FDB-CDAD-44E1-8417-885C38E49A0E}', - RootNamespace: 'ServiceStack.Text', - AssemblyName: 'ServiceStack.Text', - } -}, -{ - Path: '../src/ServiceStack.Client/ServiceStack.Client.csproj', - ReplaceElements: { - ProjectGuid: '{42E1C8C0-A163-44CC-92B1-8F416F2C0B01}', - RootNamespace: 'ServiceStack', - AssemblyName: 'ServiceStack.Client' - }, - ReplaceTexts: { - '': [ - '', - ' ', - ' {55942102-033A-4DA8-A6AF-1DB7B2F34A2D}', - ' ServiceStack.Interfaces', - ' ', - '', - '', - ' ', - ' ..\\..\\lib\\ServiceStack.Text.dll', - ' ', - '' - ].join('\n') - }, - ReplaceTemplate: function (code, tmpl) { - if (code == 'SL5') { - //tmpl = tmpl.replace(/ServiceStack.Interfaces.SL5/g, 'ServiceStack.Interfaces'); - tmpl = tmpl.replace('..\\..\\lib\\ServiceStack.Text.dll', '..\\..\\lib\\sl5\\ServiceStack.Text.dll'); - } - else if (code == 'PCL') { - tmpl = tmpl.replace('..\\..\\lib\\ServiceStack.Text.dll', '..\\..\\lib\\pcl\\ServiceStack.Text.dll'); - } - return tmpl; - } -}]; - -var CUSTOM_MERGE_FRAGMENTS = [ - ["ItemGroup", "Compile"], - ["ItemGroup", "Content"], - ["ItemGroup", "None"] -]; - -CUSTOM_TEMPLATES.forEach(function(tmpl) { - log(tmpl.Path); - var originalTemplateXml = readTextFile(tmpl.Path); - log(originalTemplateXml); - - CUSTOM_PROJS.forEach(function (proj) { - var tmplXml = originalTemplateXml; - - Object.keys(proj.ReplaceElements || {}).forEach(function (elName) { - var from = '<' + elName + '>' + tmpl[elName] + ''; - var to = '<' + elName + '>' + proj.ReplaceElements[elName] + ''; - log('\nReplaceElements(' + from + ',' + to + ')\n'); - tmplXml = tmplXml.replace(from, to); - }); - - Object.keys(proj.ReplaceTexts || {}).forEach(function (from) { - var code = tmpl.getCode ? tmpl.getCode(proj) : tmpl.Code; - var to = proj.ReplaceTexts[from].replace(/\$Code/g, code); - log('\nReplaceTexts(' + from + ',' + to + ')\n'); - tmplXml = tmplXml.replace(new RegExp(from,'g'), to); - }); - - var xml = readTextFile(proj.Path); - log(proj.Path); - //log(xml); - - CUSTOM_MERGE_FRAGMENTS.forEach(function (seekCombo) { - var strict = false; - var parser = sax.parser(strict); - - var matches = []; - var root; - var found = false; - var comboFound = []; - - parser.onopentag = function (el) { - var tag = seekCombo[0] || ''; - var tagToMatch = tag.toUpperCase(); - - if (el.name == tagToMatch) { - - var isRoot = comboFound.length == 0; - if (isRoot) { - log("found open root <" + tag + "> at: ", this.line + ":" + this.column + ", " + this.startTagPosition); - root = { line: this.line, column: this.column, startTagPosition: this.startTagPosition }; - } - - comboFound.unshift(seekCombo.shift()); - - if (seekCombo.length == 0 && !found) { - log("found open match <" + tag + "> at: ", this.line + ":" + this.column + ", " + this.startTagPosition); - found = true; - } - } - }; - - parser.onclosetag = function (name) { - if (comboFound.length > 0) { - var tag = comboFound[0]; - var tagToMatch = tag.toUpperCase(); - - if (name == tagToMatch) { - - seekCombo.unshift(comboFound.shift()); - - if (comboFound.length == 0 && found) { - log("found close at: ", this.line + ":" + this.column + ", " + this.startTagPosition); - var match = { start: root, end: { line: this.line, column: this.column, startTagPosition: this.startTagPosition } }; - matches.push(match); - found = false; - - var startPos = match.start.startTagPosition + match.start.column; - var endPos = match.end.startTagPosition - 1; - var fragment = xml.substring(startPos, endPos); - log("fragment for " + seekCombo); - log(match); - //log(fragment); - var placeholder = ""; - var withFragment = "<" + seekCombo[0] + ">\n " + fragment + ""; - tmplXml = tmplXml.replace(placeholder, withFragment); - } - } - } - }; - - parser.write(xml); - }); - - if (proj.ReplaceTemplate) { - tmplXml = proj.ReplaceTemplate(tmpl.Code, tmplXml); - } - - var customProjPath = path.join(path.dirname(proj.Path), path.basename(proj.Path).replace(".csproj", "." + tmpl.Code + ".csproj")); - log("\nwriting transformedXml to: " + customProjPath); - log(tmplXml); - - fs.writeFileSync(customProjPath, tmplXml); - }); -}); \ No newline at end of file diff --git a/build/copy-pcl.bat b/build/copy-pcl.bat deleted file mode 100644 index 2bb417ddd89..00000000000 --- a/build/copy-pcl.bat +++ /dev/null @@ -1,48 +0,0 @@ -SET MSBUILD=C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe - -REM SET BUILD=Debug -SET BUILD=Release - -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\bin\Pcl\ServiceStack.Text.dll ..\lib\pcl -COPY ..\src\ServiceStack.Client\bin\Pcl\ServiceStack.Client.* ..\lib\pcl - -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\PclExport.Net40.cs ..\src\ServiceStack.Pcl.Android -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\PclExport.Net40.cs ..\src\ServiceStack.Pcl.Ios -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\PclExport.Net40.cs ..\src\ServiceStack.Pcl.Ios10 -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\PclExport.Net40.cs ..\src\ServiceStack.Pcl.Mac20 -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\PclExport.Net40.cs ..\src\ServiceStack.Pcl.Net45 -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\PclExport.WinStore.cs ..\src\ServiceStack.Pcl.WinStore - -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\Pcl.* ..\src\ServiceStack.Pcl.Android -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\Pcl.* ..\src\ServiceStack.Pcl.Ios -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\Pcl.* ..\src\ServiceStack.Pcl.Ios10 -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\Pcl.* ..\src\ServiceStack.Pcl.Mac20 -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\Pcl.* ..\src\ServiceStack.Pcl.Net45 -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\Pcl.* ..\src\ServiceStack.Pcl.WinStore - -COPY ..\src\ServiceStack.Client\Pcl.NameValueCollectionWrapper.cs ..\src\ServiceStack.Pcl.Android -COPY ..\src\ServiceStack.Client\PclExportClient.Android.cs ..\src\ServiceStack.Pcl.Android -COPY ..\src\ServiceStack.Client\Pcl.NameValueCollectionWrapper.cs ..\src\ServiceStack.Pcl.iOS -COPY ..\src\ServiceStack.Client\Pcl.NameValueCollectionWrapper.cs ..\src\ServiceStack.Pcl.iOS10 -COPY ..\src\ServiceStack.Client\Pcl.NameValueCollectionWrapper.cs ..\src\ServiceStack.Pcl.Mac20 -COPY ..\src\ServiceStack.Client\PclExportClient.iOS.cs ..\src\ServiceStack.Pcl.iOS -COPY ..\src\ServiceStack.Client\PclExportClient.iOS.cs ..\src\ServiceStack.Pcl.iOS10 -COPY ..\src\ServiceStack.Client\Pcl.NameValueCollectionWrapper.cs ..\src\ServiceStack.Pcl.Net45 -REM COPY ..\src\ServiceStack.Client\Pcl.NameValueCollectionWrapper.cs ..\src\ServiceStack.Pcl.WinStore //Not Required -COPY ..\src\ServiceStack.Client\PclExportClient.WinStore.cs ..\src\ServiceStack.Pcl.WinStore - -COPY ..\src\ServiceStack.Client\PclExportClient.Net40.cs ..\src\ServiceStack.Pcl.Net45 -COPY ..\src\ServiceStack.Client\PclExportClient.Net40.cs ..\src\ServiceStack.Pcl.Ios -COPY ..\src\ServiceStack.Client\PclExportClient.Net40.cs ..\src\ServiceStack.Pcl.Ios10 -COPY ..\src\ServiceStack.Client\PclExportClient.Net40.cs ..\src\ServiceStack.Pcl.Mac20 -COPY ..\src\ServiceStack.Client\PclExportClient.Net40.cs ..\src\ServiceStack.Pcl.Android - -COPY ..\src\ServiceStack.Client\EncryptedServiceClient.cs ..\src\ServiceStack.Pcl.Android - -COPY ..\src\ServiceStack.Client\CryptUtils.cs ..\src\ServiceStack.Pcl.Android -COPY ..\src\ServiceStack.Client\EncryptedServiceClient.cs ..\src\ServiceStack.Pcl.iOS10 -COPY ..\src\ServiceStack.Client\CryptUtils.cs ..\src\ServiceStack.Pcl.iOS10 -COPY ..\src\ServiceStack.Client\EncryptedServiceClient.cs ..\src\ServiceStack.Pcl.Mac20 -COPY ..\src\ServiceStack.Client\CryptUtils.cs ..\src\ServiceStack.Pcl.Mac20 -COPY ..\src\ServiceStack.Client\EncryptedServiceClient.cs ..\src\ServiceStack.Pcl.Net45 -COPY ..\src\ServiceStack.Client\CryptUtils.cs ..\src\ServiceStack.Pcl.Net45 diff --git a/build/copy-sn.bat b/build/copy-sn.bat deleted file mode 100644 index 9d32a6c520f..00000000000 --- a/build/copy-sn.bat +++ /dev/null @@ -1,20 +0,0 @@ -SET BUILD=Signed - -COPY ..\src\ServiceStack.Common\bin\%BUILD%\ServiceStack.Common.dll ..\lib\signed -COPY ..\src\ServiceStack.Common\bin\%BUILD%\ServiceStack.Common.dll ..\..\ServiceStack.Redis\lib\signed -COPY ..\src\ServiceStack.Common\bin\%BUILD%\ServiceStack.Common.dll ..\..\ServiceStack.OrmLite\lib\signed - -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\bin\%BUILD%\ServiceStack.Text.dll ..\lib\signed -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\bin\%BUILD%\ServiceStack.Text.dll ..\..\ServiceStack.Redis\lib\signed -COPY ..\..\ServiceStack.Text\src\ServiceStack.Text\bin\%BUILD%\ServiceStack.Text.dll ..\..\ServiceStack.OrmLite\lib\signed - -COPY ..\src\ServiceStack.Client\bin\%BUILD%\ServiceStack.Client.dll ..\lib\signed - -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.dll ..\lib\signed - -COPY ..\..\ServiceStack.OrmLite\src\ServiceStack.OrmLite\bin\%BUILD%\ServiceStack.OrmLite.dll ..\lib\signed -COPY ..\..\ServiceStack.OrmLite\src\ServiceStack.OrmLite\bin\%BUILD%\ServiceStack.OrmLite.dll ..\..\ServiceStack.OrmLite\lib\signed - -COPY ..\..\ServiceStack.Redis\src\ServiceStack.Redis\bin\%BUILD%\ServiceStack.Redis.dll ..\lib\signed -COPY ..\..\ServiceStack.OrmLite\src\ServiceStack.OrmLite.SqlServer\bin\%BUILD%\ServiceStack.OrmLite.SqlServer.dll ..\lib\signed - diff --git a/build/copy.bat b/build/copy.bat deleted file mode 100644 index 0b8ee58de0c..00000000000 --- a/build/copy.bat +++ /dev/null @@ -1,86 +0,0 @@ -SET MSBUILD=C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe - -REM SET BUILD=Debug -SET BUILD=Release - -REM %MSBUILD% build.msbuild - -MD ..\NuGet\ServiceStack\lib\net45 -MD ..\NuGet\ServiceStack.Api.Swagger\lib\net45 -MD ..\NuGet\ServiceStack.Common\lib\net45 -MD ..\NuGet\ServiceStack.Mvc\lib\net45 -MD ..\NuGet\ServiceStack.Razor\lib\net45 -MD ..\NuGet\ServiceStack.Authentication.OpenId\lib\net45 -MD ..\NuGet\ServiceStack.Authentication.OAuth2\lib\net45 -MD ..\NuGet\ServiceStack.ProtoBuf\lib\net45 -MD ..\NuGet\ServiceStack.MsgPack\lib\net45 - -COPY ..\src\ServiceStack.Razor\bin\%BUILD%\ServiceStack.Razor.* ..\NuGet\ServiceStack.Razor\lib\net45 - -COPY ..\src\ServiceStack.Mvc\bin\%BUILD%\ServiceStack.Mvc.* ..\NuGet\ServiceStack.Mvc\lib\net45 -COPY ..\src\ServiceStack.Mvc\bin\%BUILD%\ServiceStack.Mvc.* ..\NuGet\ServiceStack.Mvc\lib\net45 - -COPY ..\src\ServiceStack.Authentication.OpenId\bin\%BUILD%\ServiceStack.Authentication.OpenId.* ..\NuGet\ServiceStack.Authentication.OpenId\lib\net45 - -COPY ..\src\ServiceStack.Authentication.OAuth2\bin\%BUILD%\ServiceStack.Authentication.OAuth2.* ..\NuGet\ServiceStack.Authentication.OAuth2\lib\net45 - -COPY ..\src\ServiceStack.ProtoBuf\bin\%BUILD%\ServiceStack.ProtoBuf.* ..\NuGet\ServiceStack.ProtoBuf\lib\net45 - -COPY ..\lib\MsgPack.dll ..\NuGet\ServiceStack.MsgPack\lib\net45 -COPY ..\src\ServiceStack.MsgPack\bin\%BUILD%\ServiceStack.MsgPack.* ..\NuGet\ServiceStack.MsgPack\lib\net45 - -IF EXIST ..\..\swagger-ui\dist-disable ( - RMDIR ..\NuGet\ServiceStack.Api.Swagger\content\swagger-ui /s /q - MD ..\NuGet\ServiceStack.Api.Swagger\content\swagger-ui - - RMDIR ..\src\ServiceStack.Api.Swagger\swagger-ui /s /q - MD ..\src\ServiceStack.Api.Swagger\swagger-ui - - XCOPY /E ..\..\swagger-ui\dist ..\src\ServiceStack.Api.Swagger\swagger-ui -) - -COPY ..\src\ServiceStack.Api.Swagger\bin\%BUILD%\ServiceStack.Api.Swagger.* ..\NuGet\ServiceStack.Api.Swagger\lib\net35 - -COPY ..\src\ServiceStack\bin\%BUILD%\*.* ..\..\ServiceStack.Contrib\lib -COPY ..\src\ServiceStack\bin\%BUILD%\*.* ..\..\ServiceStack.RedisWebServices\lib -COPY ..\src\ServiceStack.Server\bin\%BUILD%\ServiceStack.Server.* ..\..\ServiceStack.RedisWebServices\lib - -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Text.* ..\..\ServiceStack.Redis\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Common.* ..\..\ServiceStack.Redis\lib -COPY ..\src\ServiceStack.Server\bin\%BUILD%\ServiceStack.* ..\..\ServiceStack.Redis\lib\tests -COPY ..\tests\ServiceStack.Messaging.Tests\bin\%BUILD%\ServiceStack.Messaging.Tests.* ..\..\ServiceStack.Redis\lib\tests - -COPY ..\tests\ServiceStack.Common.Tests\bin\%BUILD%\ServiceStack.Common.Tests.* ..\..\ServiceStack.Text\lib\tests -COPY ..\tests\ServiceStack.Common.Tests\bin\%BUILD%\ServiceStack.Common.Tests.* ..\..\ServiceStack.Redis\lib\tests -COPY ..\tests\ServiceStack.Common.Tests\bin\%BUILD%\ServiceStack.Common.Tests.* ..\..\ServiceStack.OrmLite\lib\tests -COPY ..\src\ServiceStack.Server\bin\%BUILD%\ServiceStack.* ..\..\ServiceStack.Text\lib\tests -COPY ..\src\ServiceStack.Server\bin\%BUILD%\ServiceStack.* ..\..\ServiceStack.Rediss\lib\tests -COPY ..\src\ServiceStack.Server\bin\%BUILD%\ServiceStack.* ..\..\ServiceStack.OrmLite\lib\tests - -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.dll ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.pdb ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Text.dll ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Text.pdb ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Common.dll ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Common.pdb ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Client.dll ..\..\ServiceStack.OrmLite\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Client.pdb ..\..\ServiceStack.OrmLite\lib -COPY ..\tests\ServiceStack.Common.Tests\bin\%BUILD%\ServiceStack.Common.Tests.* ..\..\ServiceStack.OrmLite\lib\tests - -COPY ..\src\ServiceStack.Interfaces\bin\Pcl\ServiceStack.Interfaces.* ..\lib -COPY ..\src\ServiceStack.Common\bin\%BUILD%\ServiceStack.Common.* ..\lib -COPY ..\src\ServiceStack.Client\bin\%BUILD%\ServiceStack.Client.* ..\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.dll ..\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.pdb ..\lib - -COPY ..\lib\ServiceStack.Interfaces.dll ..\..\ServiceStack.Text\lib -COPY ..\lib\ServiceStack.Interfaces.dll ..\..\ServiceStack.Redis\lib -COPY ..\lib\ServiceStack.Interfaces.dll ..\..\ServiceStack.OrmLite\lib - -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Client.dll ..\..\Stripe\lib -COPY ..\src\ServiceStack\bin\%BUILD%\ServiceStack.Client.pdb ..\..\Stripe\lib -COPY ..\lib\ServiceStack.Interfaces.dll ..\..\Stripe\lib - -COPY ..\src\ServiceStack.Razor.BuildTask\bin\%BUILD%\ServiceStack.Razor.BuildTask.dll ..\lib - -REM COPY ..\src\ServiceStack.DtoGen\*.cs ..\src\ServiceStack\DtoGen diff --git a/build/node.exe b/build/node.exe deleted file mode 100644 index a139fd213e8..00000000000 Binary files a/build/node.exe and /dev/null differ diff --git a/build/node_modules/sax/AUTHORS b/build/node_modules/sax/AUTHORS deleted file mode 100644 index 7145cbcd99c..00000000000 --- a/build/node_modules/sax/AUTHORS +++ /dev/null @@ -1,10 +0,0 @@ -# contributors sorted by whether or not they're me. -Isaac Z. Schlueter -Stein Martin Hustad -Mikeal Rogers -Laurie Harper -Jann Horn -Elijah Insua -Henry Rawas -Justin Makeig -Mike Schilling diff --git a/build/node_modules/sax/LICENSE b/build/node_modules/sax/LICENSE deleted file mode 100644 index 62e4ccf916e..00000000000 --- a/build/node_modules/sax/LICENSE +++ /dev/null @@ -1,32 +0,0 @@ -Copyright (c) Isaac Z. Schlueter ("Author") -All rights reserved. - -The BSD License - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -The file "examples/strict.dtd" is licensed by the W3C and used according -to the terms of the W3C SOFTWARE NOTICE AND LICENSE. See LICENSE-W3C.html -for details. diff --git a/build/node_modules/sax/LICENSE-W3C.html b/build/node_modules/sax/LICENSE-W3C.html deleted file mode 100644 index a611e3f907f..00000000000 --- a/build/node_modules/sax/LICENSE-W3C.html +++ /dev/null @@ -1,188 +0,0 @@ - -W3C Software Notice and License
      - - - -
      -

      - W3C - -

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

      W3C Software Notice and License

      -
      -
      -

      This work (and included software, documentation such as READMEs, or other -related items) is being provided by the copyright holders under the following -license.

      -

      License

      - -

      -By obtaining, using and/or copying this work, you (the licensee) -agree that you have read, understood, and will comply with the following -terms and conditions.

      - -

      Permission to copy, modify, and distribute this software and its -documentation, with or without modification, for any purpose and without -fee or royalty is hereby granted, provided that you include the following on -ALL copies of the software and documentation or portions thereof, including -modifications:

      - -
      • The full text of this NOTICE in a location viewable to users of the - redistributed or derivative work.
      • Any pre-existing intellectual property disclaimers, notices, or terms - and conditions. If none exist, the W3C Software Short - Notice should be included (hypertext is preferred, text is permitted) - within the body of any redistributed or derivative code.
      • Notice of any changes or modifications to the files, including the date - changes were made. (We recommend you provide URIs to the location from - which the code is derived.)
      - -

      Disclaimers

      - -

      THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS -MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR -PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE -ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

      - -

      COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR -DOCUMENTATION.

      - -

      The name and trademarks of copyright holders may NOT be used in -advertising or publicity pertaining to the software without specific, written -prior permission. Title to copyright in this software and any associated -documentation will at all times remain with copyright holders.

      - -

      Notes

      - -

      This version: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231

      - -

      This formulation of W3C's notice and license became active on December 31 -2002. This version removes the copyright ownership notice such that this -license can be used with materials other than those owned by the W3C, -reflects that ERCIM is now a host of the W3C, includes references to this -specific dated version of the license, and removes the ambiguous grant of -"use". Otherwise, this version is the same as the previous -version and is written so as to preserve the Free -Software Foundation's assessment of GPL compatibility and OSI's certification -under the Open Source -Definition.

      -
      -
      -
      -
      - - - -
      - -
      diff --git a/build/node_modules/sax/README.md b/build/node_modules/sax/README.md deleted file mode 100644 index c9652420c1a..00000000000 --- a/build/node_modules/sax/README.md +++ /dev/null @@ -1,216 +0,0 @@ -# sax js - -A sax-style parser for XML and HTML. - -Designed with [node](http://nodejs.org/) in mind, but should work fine in -the browser or other CommonJS implementations. - -## What This Is - -* A very simple tool to parse through an XML string. -* A stepping stone to a streaming HTML parser. -* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML - docs. - -## What This Is (probably) Not - -* An HTML Parser - That's a fine goal, but this isn't it. It's just - XML. -* A DOM Builder - You can use it to build an object model out of XML, - but it doesn't do that out of the box. -* XSLT - No DOM = no querying. -* 100% Compliant with (some other SAX implementation) - Most SAX - implementations are in Java and do a lot more than this does. -* An XML Validator - It does a little validation when in strict mode, but - not much. -* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic - masochism. -* A DTD-aware Thing - Fetching DTDs is a much bigger job. - -## Regarding `Hello, world!').close(); - - // stream usage - // takes the same options as the parser - var saxStream = require("sax").createStream(strict, options) - saxStream.on("error", function (e) { - // unhandled errors will throw, since this is a proper node - // event emitter. - console.error("error!", e) - // clear the error - this._parser.error = null - this._parser.resume() - }) - saxStream.on("opentag", function (node) { - // same object as above - }) - // pipe is supported, and it's readable/writable - // same chunks coming in also go out. - fs.createReadStream("file.xml") - .pipe(saxStream) - .pipe(fs.createWriteStream("file-copy.xml")) - - - -## Arguments - -Pass the following arguments to the parser function. All are optional. - -`strict` - Boolean. Whether or not to be a jerk. Default: `false`. - -`opt` - Object bag of settings regarding string formatting. All default to `false`. - -Settings supported: - -* `trim` - Boolean. Whether or not to trim text and comment nodes. -* `normalize` - Boolean. If true, then turn any whitespace into a single - space. -* `lowercase` - Boolean. If true, then lowercase tag names and attribute names - in loose mode, rather than uppercasing them. -* `xmlns` - Boolean. If true, then namespaces are supported. -* `position` - Boolean. If false, then don't track line/col/position. - -## Methods - -`write` - Write bytes onto the stream. You don't have to do this all at -once. You can keep writing as much as you want. - -`close` - Close the stream. Once closed, no more data may be written until -it is done processing the buffer, which is signaled by the `end` event. - -`resume` - To gracefully handle errors, assign a listener to the `error` -event. Then, when the error is taken care of, you can call `resume` to -continue parsing. Otherwise, the parser will not continue while in an error -state. - -## Members - -At all times, the parser object will have the following members: - -`line`, `column`, `position` - Indications of the position in the XML -document where the parser currently is looking. - -`startTagPosition` - Indicates the position where the current tag starts. - -`closed` - Boolean indicating whether or not the parser can be written to. -If it's `true`, then wait for the `ready` event to write again. - -`strict` - Boolean indicating whether or not the parser is a jerk. - -`opt` - Any options passed into the constructor. - -`tag` - The current tag being dealt with. - -And a bunch of other stuff that you probably shouldn't touch. - -## Events - -All events emit with a single argument. To listen to an event, assign a -function to `on`. Functions get executed in the this-context of -the parser object. The list of supported events are also in the exported -`EVENTS` array. - -When using the stream interface, assign handlers using the EventEmitter -`on` function in the normal fashion. - -`error` - Indication that something bad happened. The error will be hanging -out on `parser.error`, and must be deleted before parsing can continue. By -listening to this event, you can keep an eye on that kind of stuff. Note: -this happens *much* more in strict mode. Argument: instance of `Error`. - -`text` - Text node. Argument: string of text. - -`doctype` - The ``. Argument: -object with `name` and `body` members. Attributes are not parsed, as -processing instructions have implementation dependent semantics. - -`sgmldeclaration` - Random SGML declarations. Stuff like `` -would trigger this kind of event. This is a weird thing to support, so it -might go away at some point. SAX isn't intended to be used to parse SGML, -after all. - -`opentag` - An opening tag. Argument: object with `name` and `attributes`. -In non-strict mode, tag names are uppercased, unless the `lowercase` -option is set. If the `xmlns` option is set, then it will contain -namespace binding information on the `ns` member, and will have a -`local`, `prefix`, and `uri` member. - -`closetag` - A closing tag. In loose mode, tags are auto-closed if their -parent closes. In strict mode, well-formedness is enforced. Note that -self-closing tags will have `closeTag` emitted immediately after `openTag`. -Argument: tag name. - -`attribute` - An attribute node. Argument: object with `name` and `value`. -In non-strict mode, attribute names are uppercased, unless the `lowercase` -option is set. If the `xmlns` option is set, it will also contains namespace -information. - -`comment` - A comment node. Argument: the string of the comment. - -`opencdata` - The opening tag of a ``) of a `` tags trigger a `"script"` -event, and their contents are not checked for special xml characters. -If you pass `noscript: true`, then this behavior is suppressed. - -## Reporting Problems - -It's best to write a failing test if you find an issue. I will always -accept pull requests with failing tests if they demonstrate intended -behavior, but it is very hard to figure out what issue you're describing -without a test. Writing a test is also the best way for you yourself -to figure out if you really understand the issue you think you have with -sax-js. diff --git a/build/node_modules/sax/component.json b/build/node_modules/sax/component.json deleted file mode 100644 index 96b5d731d09..00000000000 --- a/build/node_modules/sax/component.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "sax", - "description": "An evented streaming XML parser in JavaScript", - "author": "Isaac Z. Schlueter (http://blog.izs.me/)", - "version": "0.5.2", - "main": "lib/sax.js", - "license": "BSD", - "scripts": [ - "lib/sax.js" - ], - "repository": "git://github.com/isaacs/sax-js.git" -} diff --git a/build/node_modules/sax/examples/big-not-pretty.xml b/build/node_modules/sax/examples/big-not-pretty.xml deleted file mode 100644 index fb5265dde1a..00000000000 --- a/build/node_modules/sax/examples/big-not-pretty.xml +++ /dev/null @@ -1,8002 +0,0 @@ - - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - - something blerm a bit down here - diff --git a/build/node_modules/sax/examples/example.js b/build/node_modules/sax/examples/example.js deleted file mode 100644 index 7b0246e9ab5..00000000000 --- a/build/node_modules/sax/examples/example.js +++ /dev/null @@ -1,29 +0,0 @@ - -var fs = require("fs"), - util = require("util"), - path = require("path"), - xml = fs.readFileSync(path.join(__dirname, "test.xml"), "utf8"), - sax = require("../lib/sax"), - strict = sax.parser(true), - loose = sax.parser(false, {trim:true}), - inspector = function (ev) { return function (data) { - console.error("%s %s %j", this.line+":"+this.column, ev, data); - }}; - -sax.EVENTS.forEach(function (ev) { - loose["on"+ev] = inspector(ev); -}); -loose.onend = function () { - console.error("end"); - console.error(loose); -}; - -// do this in random bits at a time to verify that it works. -(function () { - if (xml) { - var c = Math.ceil(Math.random() * 1000) - loose.write(xml.substr(0,c)); - xml = xml.substr(c); - process.nextTick(arguments.callee); - } else loose.close(); -})(); diff --git a/build/node_modules/sax/examples/get-products.js b/build/node_modules/sax/examples/get-products.js deleted file mode 100644 index 9e8d74aacd0..00000000000 --- a/build/node_modules/sax/examples/get-products.js +++ /dev/null @@ -1,58 +0,0 @@ -// pull out /GeneralSearchResponse/categories/category/items/product tags -// the rest we don't care about. - -var sax = require("../lib/sax.js") -var fs = require("fs") -var path = require("path") -var xmlFile = path.resolve(__dirname, "shopping.xml") -var util = require("util") -var http = require("http") - -fs.readFile(xmlFile, function (er, d) { - http.createServer(function (req, res) { - if (er) throw er - var xmlstr = d.toString("utf8") - - var parser = sax.parser(true) - var products = [] - var product = null - var currentTag = null - - parser.onclosetag = function (tagName) { - if (tagName === "product") { - products.push(product) - currentTag = product = null - return - } - if (currentTag && currentTag.parent) { - var p = currentTag.parent - delete currentTag.parent - currentTag = p - } - } - - parser.onopentag = function (tag) { - if (tag.name !== "product" && !product) return - if (tag.name === "product") { - product = tag - } - tag.parent = currentTag - tag.children = [] - tag.parent && tag.parent.children.push(tag) - currentTag = tag - } - - parser.ontext = function (text) { - if (currentTag) currentTag.children.push(text) - } - - parser.onend = function () { - var out = util.inspect(products, false, 3, true) - res.writeHead(200, {"content-type":"application/json"}) - res.end("{\"ok\":true}") - // res.end(JSON.stringify(products)) - } - - parser.write(xmlstr).end() - }).listen(1337) -}) diff --git a/build/node_modules/sax/examples/hello-world.js b/build/node_modules/sax/examples/hello-world.js deleted file mode 100644 index cbfa5184ecd..00000000000 --- a/build/node_modules/sax/examples/hello-world.js +++ /dev/null @@ -1,4 +0,0 @@ -require("http").createServer(function (req, res) { - res.writeHead(200, {"content-type":"application/json"}) - res.end(JSON.stringify({ok: true})) -}).listen(1337) diff --git a/build/node_modules/sax/examples/not-pretty.xml b/build/node_modules/sax/examples/not-pretty.xml deleted file mode 100644 index 9592852d0c0..00000000000 --- a/build/node_modules/sax/examples/not-pretty.xml +++ /dev/null @@ -1,8 +0,0 @@ - - something blerm a bit down here diff --git a/build/node_modules/sax/examples/pretty-print.js b/build/node_modules/sax/examples/pretty-print.js deleted file mode 100644 index cd6aca9e1cb..00000000000 --- a/build/node_modules/sax/examples/pretty-print.js +++ /dev/null @@ -1,74 +0,0 @@ -var sax = require("../lib/sax") - , printer = sax.createStream(false, {lowercasetags:true, trim:true}) - , fs = require("fs") - -function entity (str) { - return str.replace('"', '"') -} - -printer.tabstop = 2 -printer.level = 0 -printer.indent = function () { - print("\n") - for (var i = this.level; i > 0; i --) { - for (var j = this.tabstop; j > 0; j --) { - print(" ") - } - } -} -printer.on("opentag", function (tag) { - this.indent() - this.level ++ - print("<"+tag.name) - for (var i in tag.attributes) { - print(" "+i+"=\""+entity(tag.attributes[i])+"\"") - } - print(">") -}) - -printer.on("text", ontext) -printer.on("doctype", ontext) -function ontext (text) { - this.indent() - print(text) -} - -printer.on("closetag", function (tag) { - this.level -- - this.indent() - print("") -}) - -printer.on("cdata", function (data) { - this.indent() - print("") -}) - -printer.on("comment", function (comment) { - this.indent() - print("") -}) - -printer.on("error", function (error) { - console.error(error) - throw error -}) - -if (!process.argv[2]) { - throw new Error("Please provide an xml file to prettify\n"+ - "TODO: read from stdin or take a file") -} -var xmlfile = require("path").join(process.cwd(), process.argv[2]) -var fstr = fs.createReadStream(xmlfile, { encoding: "utf8" }) - -function print (c) { - if (!process.stdout.write(c)) { - fstr.pause() - } -} - -process.stdout.on("drain", function () { - fstr.resume() -}) - -fstr.pipe(printer) diff --git a/build/node_modules/sax/examples/shopping.xml b/build/node_modules/sax/examples/shopping.xml deleted file mode 100644 index 223c6c66562..00000000000 --- a/build/node_modules/sax/examples/shopping.xml +++ /dev/null @@ -1,2 +0,0 @@ - -sandbox3.1 r31.Kadu4DC.phase357782011.10.06 15:37:23 PSTp2.a121bc2aaf029435dce62011-10-21T18:38:45.982-04:00P0Y0M0DT0H0M0.169S1112You are currently using the SDC API sandbox environment! No clicks to merchant URLs from this response will be paid. Please change the host of your API requests to 'publisher.api.shopping.com' when you have finished development and testinghttp://statTest.dealtime.com/pixel/noscript?PV_EvnTyp=APPV&APPV_APITSP=10%2F21%2F11_06%3A38%3A45_PM&APPV_DSPRQSID=p2.a121bc2aaf029435dce6&APPV_IMGURL=http://img.shopping.com/sc/glb/sdc_logo_106x19.gif&APPV_LI_LNKINID=7000610&APPV_LI_SBMKYW=nikon&APPV_MTCTYP=1000&APPV_PRTID=2002&APPV_BrnID=14804http://www.shopping.com/digital-cameras/productsDigital CamerasDigital CamerasElectronicshttp://www.shopping.com/xCH-electronics-nikon~linkin_id-7000610?oq=nikonCameras and Photographyhttp://www.shopping.com/xCH-cameras_and_photography-nikon~linkin_id-7000610?oq=nikonDigital Camerashttp://www.shopping.com/digital-cameras/nikon/products?oq=nikon&linkin_id=7000610nikonnikonDigital Camerashttp://www.shopping.com/digital-cameras/nikon/products?oq=nikon&linkin_id=7000610Nikon D3100 Digital Camera14.2 Megapixel, SLR Camera, 3 in. LCD Screen, With High Definition Video, Weight: 1 lb.The Nikon D3100 digital SLR camera speaks to the growing ranks of enthusiastic D-SLR users and aspiring photographers by providing an easy-to-use and affordable entrance to the world of Nikon D-SLR’s. The 14.2-megapixel D3100 has powerful features, such as the enhanced Guide Mode that makes it easy to unleash creative potential and capture memories with still images and full HD video. Like having a personal photo tutor at your fingertips, this unique feature provides a simple graphical interface on the camera’s LCD that guides users by suggesting and/or adjusting camera settings to achieve the desired end result images. The D3100 is also the world’s first D-SLR to introduce full time auto focus (AF) in Live View and D-Movie mode to effortlessly achieve the critical focus needed when shooting Full HD 1080p video.http://di1.shopping.com/images/pi/93/bc/04/101677489-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=1http://di1.shopping.com/images/pi/93/bc/04/101677489-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=1http://di1.shopping.com/images/pi/93/bc/04/101677489-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=1http://di1.shopping.com/images/pi/93/bc/04/101677489-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=1http://di1.shopping.com/images/pi/93/bc/04/101677489-606x500-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=194.56http://img.shopping.com/sc/pr/sdc_stars_sm_4.5.gifhttp://www.shopping.com/Nikon-D3100/reviews~linkin_id-7000610429.001360.00http://www.shopping.com/Nikon-D3100/prices~linkin_id-7000610http://www.shopping.com/Nikon-D3100/info~linkin_id-7000610Nikon D3100 Digital SLR Camera with 18-55mm NIKKOR VR LensThe Nikon D3100 Digital SLR Camera is an affordable compact and lightweight photographic power-house. It features the all-purpose 18-55mm VR lens a high-resolution 14.2 MP CMOS sensor along with a feature set that's comprehensive yet easy to navigate - the intuitive onboard learn-as-you grow guide mode allows the photographer to understand what the 3100 can do quickly and easily. Capture beautiful pictures and amazing Full HD 1080p movies with sound and full-time autofocus. Availabilty: In Stock!7185Nikonhttp://di102.shopping.com/images/di/2d/5a/57/36424d5a717a366662532d61554c7767615f67-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di102.shopping.com/images/di/2d/5a/57/36424d5a717a366662532d61554c7767615f67-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di102.shopping.com/images/di/2d/5a/57/36424d5a717a366662532d61554c7767615f67-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di102.shopping.com/images/di/2d/5a/57/36424d5a717a366662532d61554c7767615f67-350x350-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1in-stockFree Shipping with Any Purchase!529.000.00799.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=647&BEFID=7185&aon=%5E1&MerchantID=475674&crawler_id=475674&dealId=-ZW6BMZqz6fbS-aULwga_g%3D%3D&url=http%3A%2F%2Fwww.fumfie.com%2Fproduct%2F343.5%2Fshopping-com%3F&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D3100+Digital+SLR+Camera+with+18-55mm+NIKKOR+VR+Lens&dlprc=529.0&crn=&istrsmrc=1&isathrsl=0&AR=1&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=101677489&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=1&cid=&semid1=&semid2=&IsLps=0&CC=1&SL=1&FS=1&code=&acode=658&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=FumFiehttp://img.shopping.com/cctool/merch_logos/475674.gif866 666 91985604.27http://img.shopping.com/sc/mr/sdc_checks_45.gifhttp://www.shopping.com/xMR-store_fumfie~MRD-475674~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUSF343C5Nikon Nikon D3100 14.2MP Digital SLR Camera with 18-55mm f/3.5-5.6 AF-S DX VR, CamerasNikon D3100 14.2MP Digital SLR Camera with 18-55mm f/3.5-5.6 AF-S DX VR7185Nikonhttp://di109.shopping.com/images/di/6d/64/31/65396c443876644f7534464851664a714b6e67-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di109.shopping.com/images/di/6d/64/31/65396c443876644f7534464851664a714b6e67-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di109.shopping.com/images/di/6d/64/31/65396c443876644f7534464851664a714b6e67-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di109.shopping.com/images/di/6d/64/31/65396c443876644f7534464851664a714b6e67-385x352-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2in-stock549.000.00549.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=779&BEFID=7185&aon=%5E1&MerchantID=305814&crawler_id=305814&dealId=md1e9lD8vdOu4FHQfJqKng%3D%3D&url=http%3A%2F%2Fwww.electronics-expo.com%2Findex.php%3Fpage%3Ditem%26id%3DNIKD3100%26source%3DSideCar%26scpid%3D8%26scid%3Dscsho318727%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+Nikon+D3100+14.2MP+Digital+SLR+Camera+with+18-55mm+f%2F3.5-5.6+AF-S+DX+VR%2C+Cameras&dlprc=549.0&crn=&istrsmrc=1&isathrsl=0&AR=9&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=101677489&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=9&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=771&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Electronics Expohttp://img.shopping.com/cctool/merch_logos/305814.gif1-888-707-EXPO3713.90http://img.shopping.com/sc/mr/sdc_checks_4.gifhttp://www.shopping.com/xMR-store_electronics_expo~MRD-305814~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUSNIKD3100Nikon D3100 14.2-Megapixel Digital SLR Camera With 18-55mm Zoom-Nikkor Lens, BlackSplit-second shutter response captures shots other cameras may have missed Helps eliminate the frustration of shutter delay! 14.2-megapixels for enlargements worth framing and hanging. Takes breathtaking 1080p HD movies. ISO sensitivity from 100-1600 for bright or dimly lit settings. 3.0in. color LCD for beautiful, wide-angle framing and viewing. In-camera image editing lets you retouch with no PC. Automatic scene modes include Child, Sports, Night Portrait and more. Accepts SDHC memory cards. Nikon D3100 14.2-Megapixel Digital SLR Camera With 18-55mm Zoom-Nikkor Lens, Black is one of many Digital SLR Cameras available through Office Depot. Made by Nikon.7185Nikonhttp://di109.shopping.com/images/di/79/59/75/61586e4446744359377244556a6b5932616177-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di109.shopping.com/images/di/79/59/75/61586e4446744359377244556a6b5932616177-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di109.shopping.com/images/di/79/59/75/61586e4446744359377244556a6b5932616177-250x250-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3in-stock549.990.00699.99http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=698&BEFID=7185&aon=%5E1&MerchantID=467671&crawler_id=467671&dealId=yYuaXnDFtCY7rDUjkY2aaw%3D%3D&url=http%3A%2F%2Flink.mercent.com%2Fredirect.ashx%3Fmr%3AmerchantID%3DOfficeDepot%26mr%3AtrackingCode%3DCEC9669E-6ABC-E011-9F24-0019B9C043EB%26mr%3AtargetUrl%3Dhttp%3A%2F%2Fwww.officedepot.com%2Fa%2Fproducts%2F486292%2FNikon-D3100-142-Megapixel-Digital-SLR%2F%253fcm_mmc%253dMercent-_-Shopping-_-Cameras_and_Camcorders-_-486292&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D3100+14.2-Megapixel+Digital+SLR+Camera+With+18-55mm+Zoom-Nikkor+Lens%2C+Black&dlprc=549.99&crn=&istrsmrc=1&isathrsl=0&AR=10&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=101677489&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=10&cid=&semid1=&semid2=&IsLps=0&CC=1&SL=1&FS=1&code=&acode=690&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Office Depothttp://img.shopping.com/cctool/merch_logos/467671.gif1-800-GO-DEPOT1352.37http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_office_depot_4158555~MRD-467671~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS486292Nikon® D3100™ 14.2MP Digital SLR with 18-55mm LensThe Nikon D3100 DSLR will surprise you with its simplicity and impress you with superb results.7185Nikonhttp://di103.shopping.com/images/di/52/6c/35/36553743756954597348344d475a30326c7851-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di103.shopping.com/images/di/52/6c/35/36553743756954597348344d475a30326c7851-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di103.shopping.com/images/di/52/6c/35/36553743756954597348344d475a30326c7851-220x220-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4in-stock549.996.05549.99http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=504&BEFID=7185&aon=%5E1&MerchantID=332477&crawler_id=332477&dealId=Rl56U7CuiTYsH4MGZ02lxQ%3D%3D&url=http%3A%2F%2Ftracking.searchmarketing.com%2Fgsic.asp%3Faid%3D903483107%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon%C2%AE+D3100%E2%84%A2+14.2MP+Digital+SLR+with+18-55mm+Lens&dlprc=549.99&crn=&istrsmrc=0&isathrsl=0&AR=11&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=101677489&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=11&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=0&code=&acode=496&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RadioShackhttp://img.shopping.com/cctool/merch_logos/332477.gif242.25http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_radioshack_9689~MRD-332477~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS9614867Nikon D3100 SLR w/Nikon 18-55mm VR & 55-200mm VR Lenses14.2 Megapixels3" LCDLive ViewHD 1080p Video w/ Sound & Autofocus11-point Autofocus3 Frames per Second ShootingISO 100 to 3200 (Expand to 12800-Hi2)Self Cleaning SensorEXPEED 2, Image Processing EngineScene Recognition System7185Nikonhttp://di105.shopping.com/images/di/68/75/53/36785a4b444b614b4d544d5037316549364441-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di105.shopping.com/images/di/68/75/53/36785a4b444b614b4d544d5037316549364441-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di105.shopping.com/images/di/68/75/53/36785a4b444b614b4d544d5037316549364441-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di105.shopping.com/images/di/68/75/53/36785a4b444b614b4d544d5037316549364441-345x345-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5in-stock695.000.00695.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=371&BEFID=7185&aon=%5E1&MerchantID=487342&crawler_id=487342&dealId=huS6xZKDKaKMTMP71eI6DA%3D%3D&url=http%3A%2F%2Fwww.rythercamera.com%2Fcatalog%2Fproduct_info.php%3Fcsv%3Dsh%26products_id%3D32983%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D3100+SLR+w%2FNikon+18-55mm+VR+%26+55-200mm+VR+Lenses&dlprc=695.0&crn=&istrsmrc=0&isathrsl=0&AR=15&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=101677489&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=15&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=379&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RytherCamera.comhttp://img.shopping.com/cctool/merch_logos/487342.gif1-877-644-75930http://img.shopping.com/sc/glb/flag/US.gifUS32983Nikon COOLPIX S203 Digital Camera10 Megapixel, Ultra-Compact Camera, 2.5 in. LCD Screen, 3x Optical Zoom, With Video Capability, Weight: 0.23 lb.With 10.34 mega pixel, electronic VR vibration reduction, 5-level brightness adjustment, 3x optical zoom, and TFT LCD, Nikon Coolpix s203 fulfills all the demands of any photographer. The digital camera has an inbuilt memory of 44MB and an external memory slot made for all kinds of SD (Secure Digital) cards.http://di1.shopping.com/images/pi/c4/ef/1b/95397883-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=2http://di1.shopping.com/images/pi/c4/ef/1b/95397883-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=2http://di1.shopping.com/images/pi/c4/ef/1b/95397883-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=2http://di1.shopping.com/images/pi/c4/ef/1b/95397883-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=2http://di1.shopping.com/images/pi/c4/ef/1b/95397883-500x499-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=20139.00139.00http://www.shopping.com/Nikon-Coolpix-S203/prices~linkin_id-7000610http://www.shopping.com/Nikon-Coolpix-S203/info~linkin_id-7000610Nikon Coolpix S203 Digital Camera (Red)With 10.34 mega pixel, electronic VR vibration reduction, 5-level brightness adjustment, 3x optical zoom, and TFT LCD, Nikon Coolpix s203 fulfills all the demands of any photographer. The digital camera has an inbuilt memory of 44MB and an external memory slot made for all kinds of SD (Secure Digital) cards.7185Nikonhttp://di108.shopping.com/images/di/73/42/64/324a6e4945504d2d415f6c42414d31525a6751-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di108.shopping.com/images/di/73/42/64/324a6e4945504d2d415f6c42414d31525a6751-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di108.shopping.com/images/di/73/42/64/324a6e4945504d2d415f6c42414d31525a6751-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di108.shopping.com/images/di/73/42/64/324a6e4945504d2d415f6c42414d31525a6751-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di108.shopping.com/images/di/73/42/64/324a6e4945504d2d415f6c42414d31525a6751-500x500-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1in-stockFantastic prices with ease & comfort of Amazon.com!139.009.50139.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=566&BEFID=7185&aon=%5E1&MerchantID=301531&crawler_id=1903313&dealId=sBd2JnIEPM-A_lBAM1RZgQ%3D%3D&url=http%3A%2F%2Fwww.amazon.com%2Fdp%2FB002T964IM%2Fref%3Dasc_df_B002T964IM1751618%3Fsmid%3DA22UHVNXG98FAT%26tag%3Ddealtime-ce-mp01feed-20%26linkCode%3Dasn%26creative%3D395105%26creativeASIN%3DB002T964IM&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+Coolpix+S203+Digital+Camera+%28Red%29&dlprc=139.0&crn=&istrsmrc=0&isathrsl=0&AR=63&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=95397883&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=63&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=0&code=&acode=518&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Amazon Marketplacehttp://img.shopping.com/cctool/merch_logos/301531.gif2132.73http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_amazon_marketplace_9689~MRD-301531~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUSB002T964IMNikon S3100 Digital Camera14.5 Megapixel, Compact Camera, 2.7 in. LCD Screen, 5x Optical Zoom, With High Definition Video, Weight: 0.23 lb.This digital camera features a wide-angle optical Zoom-NIKKOR glass lens that allows you to capture anything from landscapes to portraits to action shots. The high-definition movie mode with one-touch recording makes it easy to capture video clips.http://di1.shopping.com/images/pi/66/2d/33/106834268-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=3http://di1.shopping.com/images/pi/66/2d/33/106834268-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=3http://di1.shopping.com/images/pi/66/2d/33/106834268-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=3http://di1.shopping.com/images/pi/66/2d/33/106834268-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=3http://di1.shopping.com/images/pi/66/2d/33/106834268-507x387-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=312.00http://img.shopping.com/sc/pr/sdc_stars_sm_2.gifhttp://www.shopping.com/nikon-s3100/reviews~linkin_id-700061099.95134.95http://www.shopping.com/nikon-s3100/prices~linkin_id-7000610http://www.shopping.com/nikon-s3100/info~linkin_id-7000610CoolPix S3100 14 Megapixel Compact Digital Camera- RedNikon Coolpix S3100 - Digital camera - compact - 14.0 Mpix - optical zoom: 5 x - supported memory: SD, SDXC, SDHC - red7185Nikonhttp://di111.shopping.com/images/di/55/55/79/476f71563872302d78726b6e2d726e474e6267-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di111.shopping.com/images/di/55/55/79/476f71563872302d78726b6e2d726e474e6267-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di111.shopping.com/images/di/55/55/79/476f71563872302d78726b6e2d726e474e6267-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di111.shopping.com/images/di/55/55/79/476f71563872302d78726b6e2d726e474e6267-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1in-stockGet 30 days FREE SHIPPING w/ ShipVantage119.956.95139.95http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=578&BEFID=7185&aon=%5E1&MerchantID=485615&crawler_id=485615&dealId=UUyGoqV8r0-xrkn-rnGNbg%3D%3D&url=http%3A%2F%2Fsears.rdr.channelintelligence.com%2Fgo.asp%3FfVhzOGNRAAQIASNiE1NbQBJpFHJ3Yx0CTAICI2BbH1lEFmgKP3QvUVpEREdlfUAUHAQPLVpFTVdtJzxAHUNYW3AhQBM0QhFvEXAbYh8EAAVmDAJeU1oyGG0GcBdhGwUGCAVqYF9SO0xSN1sZdmA7dmMdBQAJB24qX1NbQxI6AjA2ME5dVFULPDsGPFcQTTdaLTA6SR0OFlQvPAwMDxYcYlxIVkcoLTcCDA%3D%3D%26nAID%3D13736960%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=CoolPix+S3100+14+Megapixel+Compact+Digital+Camera-+Red&dlprc=119.95&crn=&istrsmrc=1&isathrsl=0&AR=28&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=106834268&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=28&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=1&FS=0&code=&acode=583&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Searshttp://img.shopping.com/cctool/merch_logos/485615.gif1-800-349-43588882.85http://img.shopping.com/sc/mr/sdc_checks_3.gifhttp://www.shopping.com/xMR-store_sears_4189479~MRD-485615~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS00337013000COOLPIX S3100 PinkNikon Coolpix S3100 - Digital camera - compact - 14.0 Mpix - optical zoom: 5 x - supported memory: SD, SDXC, SDHC - pink7185Nikonhttp://di111.shopping.com/images/di/58/38/37/4177586c573164586f4d586b34515144546f51-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di111.shopping.com/images/di/58/38/37/4177586c573164586f4d586b34515144546f51-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di111.shopping.com/images/di/58/38/37/4177586c573164586f4d586b34515144546f51-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di111.shopping.com/images/di/58/38/37/4177586c573164586f4d586b34515144546f51-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2in-stockGet 30 days FREE SHIPPING w/ ShipVantage119.956.95139.95http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=578&BEFID=7185&aon=%5E1&MerchantID=485615&crawler_id=485615&dealId=X87AwXlW1dXoMXk4QQDToQ%3D%3D&url=http%3A%2F%2Fsears.rdr.channelintelligence.com%2Fgo.asp%3FfVhzOGNRAAQIASNiE1NbQBJpFHJxYx0CTAICI2BbH1lEFmgKP3QvUVpEREdlfUAUHAQPLVpFTVdtJzxAHUNYW3AhQBM0QhFvEXAbYh8EAAVmb2JcUFxDEGsPc3QDEkFZVQ0WFhdRW0MWbgYWDlxzdGMdAVQWRi0xDAwPFhw9TSobb05eWVVYKzsLTFVVQi5RICs3SA8MU1s2MQQKD1wf%26nAID%3D13736960%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=COOLPIX+S3100+Pink&dlprc=119.95&crn=&istrsmrc=1&isathrsl=0&AR=31&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=106834268&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=31&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=1&FS=0&code=&acode=583&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Searshttp://img.shopping.com/cctool/merch_logos/485615.gif1-800-349-43588882.85http://img.shopping.com/sc/mr/sdc_checks_3.gifhttp://www.shopping.com/xMR-store_sears_4189479~MRD-485615~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS00337015000Nikon Coolpix S3100 14.0 MP Digital Camera - SilverNikon Coolpix S3100 14.0 MP Digital Camera - Silver7185Nikonhttp://di109.shopping.com/images/di/6e/76/46/776e70664134726c413144626b736473613077-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di109.shopping.com/images/di/6e/76/46/776e70664134726c413144626b736473613077-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di109.shopping.com/images/di/6e/76/46/776e70664134726c413144626b736473613077-270x270-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3in-stock109.970.00109.97http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=803&BEFID=7185&aon=%5E&MerchantID=475774&crawler_id=475774&dealId=nvFwnpfA4rlA1Dbksdsa0w%3D%3D&url=http%3A%2F%2Fwww.thewiz.com%2Fcatalog%2Fproduct.jsp%3FmodelNo%3DS3100SILVER%26gdftrk%3DgdfV2677_a_7c996_a_7c4049_a_7c26262&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+Coolpix+S3100+14.0+MP+Digital+Camera+-+Silver&dlprc=109.97&crn=&istrsmrc=0&isathrsl=0&AR=33&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=106834268&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=33&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=797&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=TheWiz.comhttp://img.shopping.com/cctool/merch_logos/475774.gif877-542-69880http://img.shopping.com/sc/glb/flag/US.gifUS26262Nikon� COOLPIX� S3100 14MP Digital Camera (Silver)The Nikon COOLPIX S3100 is the easy way to share your life and stay connected.7185Nikonhttp://di102.shopping.com/images/di/35/47/74/614e324e6572794b7770732d5365326c2d3467-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di102.shopping.com/images/di/35/47/74/614e324e6572794b7770732d5365326c2d3467-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di102.shopping.com/images/di/35/47/74/614e324e6572794b7770732d5365326c2d3467-220x220-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4in-stock119.996.05119.99http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=504&BEFID=7185&aon=%5E1&MerchantID=332477&crawler_id=332477&dealId=5GtaN2NeryKwps-Se2l-4g%3D%3D&url=http%3A%2F%2Ftracking.searchmarketing.com%2Fgsic.asp%3Faid%3D848064082%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon%C3%AF%C2%BF%C2%BD+COOLPIX%C3%AF%C2%BF%C2%BD+S3100+14MP+Digital+Camera+%28Silver%29&dlprc=119.99&crn=&istrsmrc=0&isathrsl=0&AR=37&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=106834268&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=37&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=0&code=&acode=509&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RadioShackhttp://img.shopping.com/cctool/merch_logos/332477.gif242.25http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_radioshack_9689~MRD-332477~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS10101095COOLPIX S3100 YellowNikon Coolpix S3100 - Digital camera - compact - 14.0 Mpix - optical zoom: 5 x - supported memory: SD, SDXC, SDHC - yellow7185Nikonhttp://di107.shopping.com/images/di/61/34/33/6d305258756c5833387a436e516a5535396a77-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di107.shopping.com/images/di/61/34/33/6d305258756c5833387a436e516a5535396a77-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di107.shopping.com/images/di/61/34/33/6d305258756c5833387a436e516a5535396a77-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di107.shopping.com/images/di/61/34/33/6d305258756c5833387a436e516a5535396a77-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5in-stockGet 30 days FREE SHIPPING w/ ShipVantage119.956.95139.95http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=578&BEFID=7185&aon=%5E1&MerchantID=485615&crawler_id=485615&dealId=a43m0RXulX38zCnQjU59jw%3D%3D&url=http%3A%2F%2Fsears.rdr.channelintelligence.com%2Fgo.asp%3FfVhzOGNRAAQIASNiE1NbQBJpFHJwYx0CTAICI2BbH1lEFmgKP3QvUVpEREdlfUAUHAQPLVpFTVdtJzxAHUNYW3AhQBM0QhFvEXAbYh8EAAVmb2JcUFxDEGoPc3QDEkFZVQ0WFhdRW0MWbgYWDlxzdGMdAVQWRi0xDAwPFhw9TSobb05eWVVYKzsLTFVVQi5RICs3SA8MU1s2MQQKD1wf%26nAID%3D13736960%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=COOLPIX+S3100+Yellow&dlprc=119.95&crn=&istrsmrc=1&isathrsl=0&AR=38&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=106834268&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=38&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=1&FS=0&code=&acode=583&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Searshttp://img.shopping.com/cctool/merch_logos/485615.gif1-800-349-43588882.85http://img.shopping.com/sc/mr/sdc_checks_3.gifhttp://www.shopping.com/xMR-store_sears_4189479~MRD-485615~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS00337014000Nikon D90 Digital Camera12.3 Megapixel, Point and Shoot Camera, 3 in. LCD Screen, With Video Capability, Weight: 1.36 lb.Untitled Document Nikon D90 SLR Digital Camera With 28-80mm 75-300mm Lens Kit The Nikon D90 SLR Digital Camera, with its 12.3-megapixel DX-format CMOS, 3" High resolution LCD display, Scene Recognition System, Picture Control, Active D-Lighting, and one-button Live View, provides photo enthusiasts with the image quality and performance they need to pursue their own vision while still being intuitive enough for use as an everyday camera.http://di1.shopping.com/images/pi/52/fb/d3/99671132-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=4http://di1.shopping.com/images/pi/52/fb/d3/99671132-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=4http://di1.shopping.com/images/pi/52/fb/d3/99671132-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=4http://di1.shopping.com/images/pi/52/fb/d3/99671132-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=4http://di1.shopping.com/images/pi/52/fb/d3/99671132-499x255-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=475.00http://img.shopping.com/sc/pr/sdc_stars_sm_5.gifhttp://www.shopping.com/Nikon-D90-with-18-270mm-Lens/reviews~linkin_id-7000610689.002299.00http://www.shopping.com/Nikon-D90-with-18-270mm-Lens/prices~linkin_id-7000610http://www.shopping.com/Nikon-D90-with-18-270mm-Lens/info~linkin_id-7000610Nikon® D90 12.3MP Digital SLR Camera (Body Only)The Nikon D90 will make you rethink what a digital SLR camera can achieve.7185Nikonhttp://di106.shopping.com/images/di/47/55/35/4a4a6b70554178653548756a4237666b774141-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di106.shopping.com/images/di/47/55/35/4a4a6b70554178653548756a4237666b774141-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di106.shopping.com/images/di/47/55/35/4a4a6b70554178653548756a4237666b774141-220x220-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1in-stock1015.996.051015.99http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=504&BEFID=7185&aon=%5E1&MerchantID=332477&crawler_id=332477&dealId=GU5JJkpUAxe5HujB7fkwAA%3D%3D&url=http%3A%2F%2Ftracking.searchmarketing.com%2Fgsic.asp%3Faid%3D851830266%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon%C2%AE+D90+12.3MP+Digital+SLR+Camera+%28Body+Only%29&dlprc=1015.99&crn=&istrsmrc=0&isathrsl=0&AR=14&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=99671132&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=14&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=0&code=&acode=496&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RadioShackhttp://img.shopping.com/cctool/merch_logos/332477.gif242.25http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_radioshack_9689~MRD-332477~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS10148659Nikon D90 SLR Digital Camera (Camera Body)The Nikon D90 SLR Digital Camera with its 12.3-megapixel DX-format CCD 3" High resolution LCD display Scene Recognition System Picture Control Active D-Lighting and one-button Live View provides photo enthusiasts with the image quality and performance they need to pursue their own vision while still being intuitive enough for use as an everyday camera. In addition the D90 introduces the D-Movie mode allowing for the first time an interchangeable lens SLR camera that is capable of recording 720p HD movie clips. Availabilty: In Stock7185Nikonhttp://di109.shopping.com/images/di/58/68/55/527553432d73704262544944666f3471667a51-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di109.shopping.com/images/di/58/68/55/527553432d73704262544944666f3471667a51-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di109.shopping.com/images/di/58/68/55/527553432d73704262544944666f3471667a51-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di109.shopping.com/images/di/58/68/55/527553432d73704262544944666f3471667a51-350x350-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2in-stockFree Shipping with Any Purchase!689.000.00900.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=647&BEFID=7185&aon=%5E1&MerchantID=475674&crawler_id=475674&dealId=XhURuSC-spBbTIDfo4qfzQ%3D%3D&url=http%3A%2F%2Fwww.fumfie.com%2Fproduct%2F169.5%2Fshopping-com%3F&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+SLR+Digital+Camera+%28Camera+Body%29&dlprc=689.0&crn=&istrsmrc=1&isathrsl=0&AR=16&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=99671132&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=16&cid=&semid1=&semid2=&IsLps=0&CC=1&SL=1&FS=1&code=&acode=658&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=FumFiehttp://img.shopping.com/cctool/merch_logos/475674.gif866 666 91985604.27http://img.shopping.com/sc/mr/sdc_checks_45.gifhttp://www.shopping.com/xMR-store_fumfie~MRD-475674~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUSF169C5Nikon D90 SLR w/Nikon 18-105mm VR & 55-200mm VR Lenses12.3 MegapixelDX Format CMOS Sensor3" VGA LCD DisplayLive ViewSelf Cleaning SensorD-Movie ModeHigh Sensitivity (ISO 3200)4.5 fps BurstIn-Camera Image Editing7185Nikonhttp://di101.shopping.com/images/di/6f/30/50/785f584c5744627278415952793372436d7951-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di101.shopping.com/images/di/6f/30/50/785f584c5744627278415952793372436d7951-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di101.shopping.com/images/di/6f/30/50/785f584c5744627278415952793372436d7951-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di101.shopping.com/images/di/6f/30/50/785f584c5744627278415952793372436d7951-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di101.shopping.com/images/di/6f/30/50/785f584c5744627278415952793372436d7951-500x500-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3in-stock1189.000.001189.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=371&BEFID=7185&aon=%5E1&MerchantID=487342&crawler_id=487342&dealId=o0Px_XLWDbrxAYRy3rCmyQ%3D%3D&url=http%3A%2F%2Fwww.rythercamera.com%2Fcatalog%2Fproduct_info.php%3Fcsv%3Dsh%26products_id%3D30619%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+SLR+w%2FNikon+18-105mm+VR+%26+55-200mm+VR+Lenses&dlprc=1189.0&crn=&istrsmrc=0&isathrsl=0&AR=20&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=99671132&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=20&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=379&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RytherCamera.comhttp://img.shopping.com/cctool/merch_logos/487342.gif1-877-644-75930http://img.shopping.com/sc/glb/flag/US.gifUS30619Nikon D90 12.3 Megapixel Digital SLR Camera (Body Only)Fusing 12.3 megapixel image quality and a cinematic 24fps D-Movie Mode, the Nikon D90 exceeds the demands of passionate photographers. Coupled with Nikon's EXPEED image processing technologies and NIKKOR optics, breathtaking image fidelity is assured. Combined with fast 0.15ms power-up and split-second 65ms shooting lag, dramatic action and decisive moments are captured easily. Effective 4-frequency, ultrasonic sensor cleaning frees image degrading dust particles from the sensor's optical low pass filter.7185Nikonhttp://di110.shopping.com/images/di/34/48/67/62574a534a3873736749663842304d58497741-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di110.shopping.com/images/di/34/48/67/62574a534a3873736749663842304d58497741-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di110.shopping.com/images/di/34/48/67/62574a534a3873736749663842304d58497741-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4in-stockFREE FEDEX 2-3 DAY DELIVERY899.950.00899.95http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=269&BEFID=7185&aon=%5E&MerchantID=9296&crawler_id=811558&dealId=4HgbWJSJ8ssgIf8B0MXIwA%3D%3D&url=http%3A%2F%2Fwww.pcnation.com%2Foptics-gallery%2Fdetails.asp%3Faffid%3D305%26item%3D2N145P&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+12.3+Megapixel+Digital+SLR+Camera+%28Body+Only%29&dlprc=899.95&crn=&istrsmrc=1&isathrsl=0&AR=21&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=99671132&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=21&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=257&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=PCNationhttp://img.shopping.com/cctool/merch_logos/9296.gif800-470-707916224.43http://img.shopping.com/sc/mr/sdc_checks_45.gifhttp://www.shopping.com/xMR-store_pcnation_9689~MRD-9296~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS2N145PNikon D90 12.3MP Digital SLR Camera (Body Only)Fusing 12.3-megapixel image quality inherited from the award-winning D300 with groundbreaking features, the D90's breathtaking, low-noise image quality is further advanced with EXPEED image processing. Split-second shutter response and continuous shooting at up to 4.5 frames-per-second provide the power to capture fast action and precise moments perfectly, while Nikon's exclusive Scene Recognition System contributes to faster 11-area autofocus performance, finer white balance detection and more. The D90 delivers the control passionate photographers demand, utilizing comprehensive exposure functions and the intelligence of 3D Color Matrix Metering II. Stunning results come to life on a 3-inch 920,000-dot color LCD monitor, providing accurate image review, Live View composition and brilliant playback of the D90's cinematic-quality 24-fps HD D-Movie mode.7185Nikonhttp://di102.shopping.com/images/di/55/4e/44/6133754d445a584f6e76445f377354494c5967-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di102.shopping.com/images/di/55/4e/44/6133754d445a584f6e76445f377354494c5967-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di102.shopping.com/images/di/55/4e/44/6133754d445a584f6e76445f377354494c5967-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di102.shopping.com/images/di/55/4e/44/6133754d445a584f6e76445f377354494c5967-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di102.shopping.com/images/di/55/4e/44/6133754d445a584f6e76445f377354494c5967-500x500-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5in-stockFantastic prices with ease & comfort of Amazon.com!780.000.00780.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=566&BEFID=7185&aon=%5E1&MerchantID=301531&crawler_id=1903313&dealId=UNDa3uMDZXOnvD_7sTILYg%3D%3D&url=http%3A%2F%2Fwww.amazon.com%2Fdp%2FB001ET5U92%2Fref%3Dasc_df_B001ET5U921751618%3Fsmid%3DAHF4SYKP09WBH%26tag%3Ddealtime-ce-mp01feed-20%26linkCode%3Dasn%26creative%3D395105%26creativeASIN%3DB001ET5U92&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+12.3MP+Digital+SLR+Camera+%28Body+Only%29&dlprc=780.0&crn=&istrsmrc=0&isathrsl=0&AR=29&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=99671132&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=29&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=520&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Amazon Marketplacehttp://img.shopping.com/cctool/merch_logos/301531.gif2132.73http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_amazon_marketplace_9689~MRD-301531~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUSB001ET5U92Nikon D90 Digital Camera with 18-105mm lens12.9 Megapixel, SLR Camera, 3 in. LCD Screen, 5.8x Optical Zoom, With Video Capability, Weight: 2.3 lb.Its 12.3 megapixel DX-format CMOS image sensor and EXPEED image processing system offer outstanding image quality across a wide ISO light sensitivity range. Live View mode lets you compose and shoot via the high-resolution 3-inch LCD monitor, and an advanced Scene Recognition System and autofocus performance help capture images with astounding accuracy. Movies can be shot in Motion JPEG format using the D-Movie function. The camera’s large image sensor ensures exceptional movie image quality and you can create dramatic effects by shooting with a wide range of interchangeable NIKKOR lenses, from wide-angle to macro to fisheye, or by adjusting the lens aperture and experimenting with depth-of-field. The D90 – designed to fuel your passion for photography.http://di1.shopping.com/images/pi/57/6a/4f/70621646-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=5http://di1.shopping.com/images/pi/57/6a/4f/70621646-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=5http://di1.shopping.com/images/pi/57/6a/4f/70621646-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=5http://di1.shopping.com/images/pi/57/6a/4f/70621646-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=5http://di1.shopping.com/images/pi/57/6a/4f/70621646-490x489-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=2&c=1&l=7000610&t=111021183845&r=5324.81http://img.shopping.com/sc/pr/sdc_stars_sm_5.gifhttp://www.shopping.com/Nikon-D90-with-18-105mm-lens/reviews~linkin_id-7000610849.951599.95http://www.shopping.com/Nikon-D90-with-18-105mm-lens/prices~linkin_id-7000610http://www.shopping.com/Nikon-D90-with-18-105mm-lens/info~linkin_id-7000610Nikon D90 18-105mm VR LensThe Nikon D90 SLR Digital Camera with its 12.3-megapixel DX-format CMOS 3" High resolution LCD display Scene Recognition System Picture Control Active D-Lighting and one-button Live View prov7185Nikonhttp://di111.shopping.com/images/di/33/6f/35/6531566768674a5066684c7654314a464b5441-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di111.shopping.com/images/di/33/6f/35/6531566768674a5066684c7654314a464b5441-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1http://di111.shopping.com/images/di/33/6f/35/6531566768674a5066684c7654314a464b5441-260x260-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=1in-stock849.950.00849.95http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=419&BEFID=7185&aon=%5E1&MerchantID=9390&crawler_id=1905054&dealId=3o5e1VghgJPfhLvT1JFKTA%3D%3D&url=http%3A%2F%2Fwww.ajrichard.com%2FNikon-D90-18-105mm-VR-Lens%2Fp-292%3Frefid%3DShopping%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+18-105mm+VR+Lens&dlprc=849.95&crn=&istrsmrc=0&isathrsl=0&AR=2&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=70621646&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=2&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=425&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=AJRichardhttp://img.shopping.com/cctool/merch_logos/9390.gif1-888-871-125631244.48http://img.shopping.com/sc/mr/sdc_checks_45.gifhttp://www.shopping.com/xMR-store_ajrichard~MRD-9390~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS292Nikon D90 SLR w/Nikon 18-105mm VR Lens12.3 MegapixelDX Format CMOS Sensor3" VGA LCD DisplayLive ViewSelf Cleaning SensorD-Movie ModeHigh Sensitivity (ISO 3200)4.5 fps BurstIn-Camera Image Editing7185Nikonhttp://di108.shopping.com/images/di/5f/6c/59/576a5f6a62776673536b666377556344757777-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di108.shopping.com/images/di/5f/6c/59/576a5f6a62776673536b666377556344757777-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di108.shopping.com/images/di/5f/6c/59/576a5f6a62776673536b666377556344757777-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di108.shopping.com/images/di/5f/6c/59/576a5f6a62776673536b666377556344757777-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2http://di108.shopping.com/images/di/5f/6c/59/576a5f6a62776673536b666377556344757777-500x500-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=2in-stock909.000.00909.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=371&BEFID=7185&aon=%5E1&MerchantID=487342&crawler_id=487342&dealId=_lYWj_jbwfsSkfcwUcDuww%3D%3D&url=http%3A%2F%2Fwww.rythercamera.com%2Fcatalog%2Fproduct_info.php%3Fcsv%3Dsh%26products_id%3D30971%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+SLR+w%2FNikon+18-105mm+VR+Lens&dlprc=909.0&crn=&istrsmrc=0&isathrsl=0&AR=3&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=70621646&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=3&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=1&code=&acode=379&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RytherCamera.comhttp://img.shopping.com/cctool/merch_logos/487342.gif1-877-644-75930http://img.shopping.com/sc/glb/flag/US.gifUS3097125448/D90 12.3 Megapixel Digital Camera 18-105mm Zoom Lens w/ 3" Screen - BlackNikon D90 - Digital camera - SLR - 12.3 Mpix - Nikon AF-S DX 18-105mm lens - optical zoom: 5.8 x - supported memory: SD, SDHC7185Nikonhttp://di110.shopping.com/images/di/31/4b/43/636c4347755776747932584b5539736b616467-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di110.shopping.com/images/di/31/4b/43/636c4347755776747932584b5539736b616467-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di110.shopping.com/images/di/31/4b/43/636c4347755776747932584b5539736b616467-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3http://di110.shopping.com/images/di/31/4b/43/636c4347755776747932584b5539736b616467-400x400-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=3in-stockGet 30 days FREE SHIPPING w/ ShipVantage1199.008.201199.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=578&BEFID=7185&aon=%5E1&MerchantID=485615&crawler_id=485615&dealId=1KCclCGuWvty2XKU9skadg%3D%3D&url=http%3A%2F%2Fsears.rdr.channelintelligence.com%2Fgo.asp%3FfVhzOGNRAAQIASNiE1NbQBRtFXpzYx0CTAICI2BbH1lEFmgKP3QvUVpEREdlfUAUHAQPLVpFTVdtJzxAHUNYW3AhQBM0QhFvEXAbYh8EAAVmb2JcVlhCGGkPc3QDEkFZVQ0WFhdRW0MWbgYWDlxzdGMdAVQWRi0xDAwPFhw9TSobb05eWVVYKzsLTFVVQi5RICs3SA8MU1s2MQQKD1wf%26nAID%3D13736960%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=25448%2FD90+12.3+Megapixel+Digital+Camera+18-105mm+Zoom+Lens+w%2F+3%22+Screen+-+Black&dlprc=1199.0&crn=&istrsmrc=1&isathrsl=0&AR=4&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=70621646&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=4&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=0&code=&acode=586&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=Searshttp://img.shopping.com/cctool/merch_logos/485615.gif1-800-349-43588882.85http://img.shopping.com/sc/mr/sdc_checks_3.gifhttp://www.shopping.com/xMR-store_sears_4189479~MRD-485615~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS00353197000Nikon® D90 12.3MP Digital SLR with 18-105mm LensThe Nikon D90 will make you rethink what a digital SLR camera can achieve.7185Nikonhttp://di101.shopping.com/images/di/33/2d/56/4f53665656354a6f37486c41346b4a74616e41-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di101.shopping.com/images/di/33/2d/56/4f53665656354a6f37486c41346b4a74616e41-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4http://di101.shopping.com/images/di/33/2d/56/4f53665656354a6f37486c41346b4a74616e41-220x220-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=4in-stock1350.996.051350.99http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=504&BEFID=7185&aon=%5E1&MerchantID=332477&crawler_id=332477&dealId=3-VOSfVV5Jo7HlA4kJtanA%3D%3D&url=http%3A%2F%2Ftracking.searchmarketing.com%2Fgsic.asp%3Faid%3D982673361%26&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon%C2%AE+D90+12.3MP+Digital+SLR+with+18-105mm+Lens&dlprc=1350.99&crn=&istrsmrc=0&isathrsl=0&AR=5&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=70621646&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=5&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=0&FS=0&code=&acode=496&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=RadioShackhttp://img.shopping.com/cctool/merch_logos/332477.gif242.25http://img.shopping.com/sc/mr/sdc_checks_25.gifhttp://www.shopping.com/xMR-store_radioshack_9689~MRD-332477~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS11148905Nikon D90 Kit 12.3-megapixel Digital SLR with 18-105mm VR LensPhotographers, take your passion further!Now is the time for new creativity, and to rethink what a digital SLR camera can achieve. It's time for the D90, a camera with everything you would expect from Nikon's next-generation D-SLRs, and some unexpected surprises, as well. The stunning image quality is inherited from the D300, Nikon's DX-format flagship. The D90 also has Nikon's unmatched ergonomics and high performance, and now takes high-quality movies with beautifully cinematic results. The world of photography has changed, and with the D90 in your hands, it's time to make your own rules.AF-S DX NIKKOR 18-105mm f/3.5-5.6G ED VR LensWide-ratio 5.8x zoom Compact, versatile and ideal for a broad range of shooting situations, ranging from interiors and landscapes to beautiful portraits� a perfect everyday zoom. Nikon VR (Vibration Reduction) image stabilization Vibration Reduction is engineered specifically for each VR NIKKOR lens and enables handheld shooting at up to 3 shutter speeds slower than would7185Nikonhttp://di110.shopping.com/images/di/6b/51/6e/4236725334416a4e3564783568325f36333167-100x100-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di110.shopping.com/images/di/6b/51/6e/4236725334416a4e3564783568325f36333167-200x200-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di110.shopping.com/images/di/6b/51/6e/4236725334416a4e3564783568325f36333167-300x300-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://img.shopping.com/sc/ds/no_image_100X100.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5http://di110.shopping.com/images/di/6b/51/6e/4236725334416a4e3564783568325f36333167-300x232-0-0.jpg?p=p2.a121bc2aaf029435dce6&a=1&c=1&l=7000610&t=111021183845&r=5in-stockShipping Included!1050.000.001199.00http://statTest.dealtime.com/DealFrame/DealFrame.cmp?bm=135&BEFID=7185&aon=%5E1&MerchantID=313162&crawler_id=313162&dealId=kQnB6rS4AjN5dx5h2_631g%3D%3D&url=http%3A%2F%2Fonecall.rdr.channelintelligence.com%2Fgo.asp%3FfVhzOGNRAAQIASNiE1pZSxNoWHFwLx8GTAICa2ZeH1sPXTZLNzRpAh1HR0BxPQEGCBJNMhFHUElsFCFCVkVTTHAcBggEHQ4aHXNpGERGH3RQODsbAgdechJtbBt8fx8JAwhtZFAzJj1oGgIWCxRlNyFOUV9UUGIxBgo0T0IyTSYqJ0RWHw4QPCIBAAQXRGMDICg6TllZVBhh%26nAID%3D13736960&linkin_id=7000610&Issdt=111021183845&searchID=p2.a121bc2aaf029435dce6&DealName=Nikon+D90+Kit+12.3-megapixel+Digital+SLR+with+18-105mm+VR+Lens&dlprc=1050.0&crn=&istrsmrc=1&isathrsl=0&AR=6&NG=20&NDP=200&PN=1&ST=7&DB=sdcprod&MT=phx-pkadudc2&FPT=DSP&NDS=&NMS=&MRS=&PD=70621646&brnId=14804&IsFtr=0&IsSmart=0&DMT=&op=&CM=&DlLng=1&RR=6&cid=&semid1=&semid2=&IsLps=0&CC=0&SL=1&FS=1&code=&acode=143&category=&HasLink=&frameId=&ND=&MN=&PT=&prjID=&GR=&lnkId=&VK=OneCallhttp://img.shopping.com/cctool/merch_logos/313162.gif1.800.398.07661804.44http://img.shopping.com/sc/mr/sdc_checks_45.gifhttp://www.shopping.com/xMR-store_onecall_9689~MRD-313162~S-1~linkin_id-7000610http://img.shopping.com/sc/glb/flag/US.gifUS92826Price rangehttp://www.shopping.com/digital-cameras/nikon/products?oq=nikon&linkin_id=7000610$24 - $4012http://www.shopping.com/digital-cameras/nikon/products?minPrice=24&maxPrice=4012&linkin_id=7000610$4012 - $7999http://www.shopping.com/digital-cameras/nikon/products?minPrice=4012&maxPrice=7999&linkin_id=7000610Brandhttp://www.shopping.com/digital-cameras/nikon/products~all-9688-brand~MS-1?oq=nikon&linkin_id=7000610Nikonhttp://www.shopping.com/digital-cameras/nikon+brand-nikon/products~linkin_id-7000610Cranehttp://www.shopping.com/digital-cameras/nikon+9688-brand-crane/products~linkin_id-7000610Ikelitehttp://www.shopping.com/digital-cameras/nikon+ikelite/products~linkin_id-7000610Bowerhttp://www.shopping.com/digital-cameras/nikon+bower/products~linkin_id-7000610FUJIFILMhttp://www.shopping.com/digital-cameras/nikon+brand-fuji/products~linkin_id-7000610Storehttp://www.shopping.com/digital-cameras/nikon/products~all-store~MS-1?oq=nikon&linkin_id=7000610Amazon Marketplacehttp://www.shopping.com/digital-cameras/nikon+store-amazon-marketplace-9689/products~linkin_id-7000610Amazonhttp://www.shopping.com/digital-cameras/nikon+store-amazon/products~linkin_id-7000610Adoramahttp://www.shopping.com/digital-cameras/nikon+store-adorama/products~linkin_id-7000610J&R Music and Computer Worldhttp://www.shopping.com/digital-cameras/nikon+store-j-r-music-and-computer-world/products~linkin_id-7000610RytherCamera.comhttp://www.shopping.com/digital-cameras/nikon+store-rythercamera-com/products~linkin_id-7000610Resolutionhttp://www.shopping.com/digital-cameras/nikon/products~all-21885-resolution~MS-1?oq=nikon&linkin_id=7000610Under 4 Megapixelhttp://www.shopping.com/digital-cameras/nikon+under-4-megapixel/products~linkin_id-7000610At least 5 Megapixelhttp://www.shopping.com/digital-cameras/nikon+5-megapixel-digital-cameras/products~linkin_id-7000610At least 6 Megapixelhttp://www.shopping.com/digital-cameras/nikon+6-megapixel-digital-cameras/products~linkin_id-7000610At least 7 Megapixelhttp://www.shopping.com/digital-cameras/nikon+7-megapixel-digital-cameras/products~linkin_id-7000610At least 8 Megapixelhttp://www.shopping.com/digital-cameras/nikon+8-megapixel-digital-cameras/products~linkin_id-7000610Featureshttp://www.shopping.com/digital-cameras/nikon/products~all-32804-features~MS-1?oq=nikon&linkin_id=7000610Shockproofhttp://www.shopping.com/digital-cameras/nikon+32804-features-shockproof/products~linkin_id-7000610Waterproofhttp://www.shopping.com/digital-cameras/nikon+32804-features-waterproof/products~linkin_id-7000610Freezeproofhttp://www.shopping.com/digital-cameras/nikon+32804-features-freezeproof/products~linkin_id-7000610Dust proofhttp://www.shopping.com/digital-cameras/nikon+32804-features-dust-proof/products~linkin_id-7000610Image Stabilizationhttp://www.shopping.com/digital-cameras/nikon+32804-features-image-stabilization/products~linkin_id-7000610hybriddigital camerag1sonycameracanonnikonkodak digital camerakodaksony cybershotkodak easyshare digital cameranikon coolpixolympuspink digital cameracanon powershot \ No newline at end of file diff --git a/build/node_modules/sax/examples/strict.dtd b/build/node_modules/sax/examples/strict.dtd deleted file mode 100644 index b27455943fc..00000000000 --- a/build/node_modules/sax/examples/strict.dtd +++ /dev/null @@ -1,870 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%HTMLlat1; - - -%HTMLsymbol; - - -%HTMLspecial; - - - - - - - - - - - - - -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/node_modules/sax/examples/test.html b/build/node_modules/sax/examples/test.html deleted file mode 100644 index 61f8f1ab91c..00000000000 --- a/build/node_modules/sax/examples/test.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - testing the parser - - - -

      hello - - - - diff --git a/build/node_modules/sax/examples/test.xml b/build/node_modules/sax/examples/test.xml deleted file mode 100644 index 801292d7f27..00000000000 --- a/build/node_modules/sax/examples/test.xml +++ /dev/null @@ -1,1254 +0,0 @@ - - -]> - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - - Some Text - - - - - - - are ok in here. ]]> - - Pre-Text & Inlined text Post-text. -  - - \ No newline at end of file diff --git a/build/node_modules/sax/lib/sax.js b/build/node_modules/sax/lib/sax.js deleted file mode 100644 index 77e20ae8715..00000000000 --- a/build/node_modules/sax/lib/sax.js +++ /dev/null @@ -1,1329 +0,0 @@ -// wrapper for non-node envs -;(function (sax) { - -sax.parser = function (strict, opt) { return new SAXParser(strict, opt) } -sax.SAXParser = SAXParser -sax.SAXStream = SAXStream -sax.createStream = createStream - -// When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns. -// When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)), -// since that's the earliest that a buffer overrun could occur. This way, checks are -// as rare as required, but as often as necessary to ensure never crossing this bound. -// Furthermore, buffers are only tested at most once per write(), so passing a very -// large string into write() might have undesirable effects, but this is manageable by -// the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme -// edge case, result in creating at most one complete copy of the string passed in. -// Set to Infinity to have unlimited buffers. -sax.MAX_BUFFER_LENGTH = 64 * 1024 - -var buffers = [ - "comment", "sgmlDecl", "textNode", "tagName", "doctype", - "procInstName", "procInstBody", "entity", "attribName", - "attribValue", "cdata", "script" -] - -sax.EVENTS = // for discoverability. - [ "text" - , "processinginstruction" - , "sgmldeclaration" - , "doctype" - , "comment" - , "attribute" - , "opentag" - , "closetag" - , "opencdata" - , "cdata" - , "closecdata" - , "error" - , "end" - , "ready" - , "script" - , "opennamespace" - , "closenamespace" - ] - -function SAXParser (strict, opt) { - if (!(this instanceof SAXParser)) return new SAXParser(strict, opt) - - var parser = this - clearBuffers(parser) - parser.q = parser.c = "" - parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH - parser.opt = opt || {} - parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags - parser.looseCase = parser.opt.lowercase ? "toLowerCase" : "toUpperCase" - parser.tags = [] - parser.closed = parser.closedRoot = parser.sawRoot = false - parser.tag = parser.error = null - parser.strict = !!strict - parser.noscript = !!(strict || parser.opt.noscript) - parser.state = S.BEGIN - parser.ENTITIES = Object.create(sax.ENTITIES) - parser.attribList = [] - - // namespaces form a prototype chain. - // it always points at the current tag, - // which protos to its parent tag. - if (parser.opt.xmlns) parser.ns = Object.create(rootNS) - - // mostly just for error reporting - parser.trackPosition = parser.opt.position !== false - if (parser.trackPosition) { - parser.position = parser.line = parser.column = 0 - } - emit(parser, "onready") -} - -if (!Object.create) Object.create = function (o) { - function f () { this.__proto__ = o } - f.prototype = o - return new f -} - -if (!Object.getPrototypeOf) Object.getPrototypeOf = function (o) { - return o.__proto__ -} - -if (!Object.keys) Object.keys = function (o) { - var a = [] - for (var i in o) if (o.hasOwnProperty(i)) a.push(i) - return a -} - -function checkBufferLength (parser) { - var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10) - , maxActual = 0 - for (var i = 0, l = buffers.length; i < l; i ++) { - var len = parser[buffers[i]].length - if (len > maxAllowed) { - // Text/cdata nodes can get big, and since they're buffered, - // we can get here under normal conditions. - // Avoid issues by emitting the text node now, - // so at least it won't get any bigger. - switch (buffers[i]) { - case "textNode": - closeText(parser) - break - - case "cdata": - emitNode(parser, "oncdata", parser.cdata) - parser.cdata = "" - break - - case "script": - emitNode(parser, "onscript", parser.script) - parser.script = "" - break - - default: - error(parser, "Max buffer length exceeded: "+buffers[i]) - } - } - maxActual = Math.max(maxActual, len) - } - // schedule the next check for the earliest possible buffer overrun. - parser.bufferCheckPosition = (sax.MAX_BUFFER_LENGTH - maxActual) - + parser.position -} - -function clearBuffers (parser) { - for (var i = 0, l = buffers.length; i < l; i ++) { - parser[buffers[i]] = "" - } -} - -SAXParser.prototype = - { end: function () { end(this) } - , write: write - , resume: function () { this.error = null; return this } - , close: function () { return this.write(null) } - } - -try { - var Stream = require("stream").Stream -} catch (ex) { - var Stream = function () {} -} - - -var streamWraps = sax.EVENTS.filter(function (ev) { - return ev !== "error" && ev !== "end" -}) - -function createStream (strict, opt) { - return new SAXStream(strict, opt) -} - -function SAXStream (strict, opt) { - if (!(this instanceof SAXStream)) return new SAXStream(strict, opt) - - Stream.apply(this) - - this._parser = new SAXParser(strict, opt) - this.writable = true - this.readable = true - - - var me = this - - this._parser.onend = function () { - me.emit("end") - } - - this._parser.onerror = function (er) { - me.emit("error", er) - - // if didn't throw, then means error was handled. - // go ahead and clear error, so we can write again. - me._parser.error = null - } - - this._decoder = null; - - streamWraps.forEach(function (ev) { - Object.defineProperty(me, "on" + ev, { - get: function () { return me._parser["on" + ev] }, - set: function (h) { - if (!h) { - me.removeAllListeners(ev) - return me._parser["on"+ev] = h - } - me.on(ev, h) - }, - enumerable: true, - configurable: false - }) - }) -} - -SAXStream.prototype = Object.create(Stream.prototype, - { constructor: { value: SAXStream } }) - -SAXStream.prototype.write = function (data) { - if (typeof Buffer === 'function' && - typeof Buffer.isBuffer === 'function' && - Buffer.isBuffer(data)) { - if (!this._decoder) { - var SD = require('string_decoder').StringDecoder - this._decoder = new SD('utf8') - } - data = this._decoder.write(data); - } - - this._parser.write(data.toString()) - this.emit("data", data) - return true -} - -SAXStream.prototype.end = function (chunk) { - if (chunk && chunk.length) this.write(chunk) - else if (this.leftovers) this._parser.write(this.leftovers.toString()) - this._parser.end() - return true -} - -SAXStream.prototype.on = function (ev, handler) { - var me = this - if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) { - me._parser["on"+ev] = function () { - var args = arguments.length === 1 ? [arguments[0]] - : Array.apply(null, arguments) - args.splice(0, 0, ev) - me.emit.apply(me, args) - } - } - - return Stream.prototype.on.call(me, ev, handler) -} - - - -// character classes and tokens -var whitespace = "\r\n\t " - // this really needs to be replaced with character classes. - // XML allows all manner of ridiculous numbers and digits. - , number = "0124356789" - , letter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - // (Letter | "_" | ":") - , quote = "'\"" - , entity = number+letter+"#" - , attribEnd = whitespace + ">" - , CDATA = "[CDATA[" - , DOCTYPE = "DOCTYPE" - , XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" - , XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/" - , rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE } - -// turn all the string character sets into character class objects. -whitespace = charClass(whitespace) -number = charClass(number) -letter = charClass(letter) - -// http://www.w3.org/TR/REC-xml/#NT-NameStartChar -// This implementation works on strings, a single character at a time -// as such, it cannot ever support astral-plane characters (10000-EFFFF) -// without a significant breaking change to either this parser, or the -// JavaScript language. Implementation of an emoji-capable xml parser -// is left as an exercise for the reader. -var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ - -var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/ - -quote = charClass(quote) -entity = charClass(entity) -attribEnd = charClass(attribEnd) - -function charClass (str) { - return str.split("").reduce(function (s, c) { - s[c] = true - return s - }, {}) -} - -function isRegExp (c) { - return Object.prototype.toString.call(c) === '[object RegExp]' -} - -function is (charclass, c) { - return isRegExp(charclass) ? !!c.match(charclass) : charclass[c] -} - -function not (charclass, c) { - return !is(charclass, c) -} - -var S = 0 -sax.STATE = -{ BEGIN : S++ -, TEXT : S++ // general stuff -, TEXT_ENTITY : S++ // & and such. -, OPEN_WAKA : S++ // < -, SGML_DECL : S++ // -, SCRIPT : S++ // " - , expect : - [ [ "opentag", { name: "xml", attributes: {}, isSelfClosing: false } ] - , [ "opentag", { name: "script", attributes: {}, isSelfClosing: false } ] - , [ "text", "hello world" ] - , [ "closetag", "script" ] - , [ "closetag", "xml" ] - ] - , strict : false - , opt : { lowercasetags: true, noscript: true } - } - ) - -require(__dirname).test - ( { xml : "" - , expect : - [ [ "opentag", { name: "xml", attributes: {}, isSelfClosing: false } ] - , [ "opentag", { name: "script", attributes: {}, isSelfClosing: false } ] - , [ "opencdata", undefined ] - , [ "cdata", "hello world" ] - , [ "closecdata", undefined ] - , [ "closetag", "script" ] - , [ "closetag", "xml" ] - ] - , strict : false - , opt : { lowercasetags: true, noscript: true } - } - ) - diff --git a/build/node_modules/sax/test/issue-84.js b/build/node_modules/sax/test/issue-84.js deleted file mode 100644 index 0e7ee699abc..00000000000 --- a/build/node_modules/sax/test/issue-84.js +++ /dev/null @@ -1,13 +0,0 @@ -// https://github.com/isaacs/sax-js/issues/49 -require(__dirname).test - ( { xml : "body" - , expect : - [ [ "processinginstruction", { name: "has", body: "unbalanced \"quotes" } ], - [ "opentag", { name: "xml", attributes: {}, isSelfClosing: false } ] - , [ "text", "body" ] - , [ "closetag", "xml" ] - ] - , strict : false - , opt : { lowercasetags: true, noscript: true } - } - ) diff --git a/build/node_modules/sax/test/parser-position.js b/build/node_modules/sax/test/parser-position.js deleted file mode 100644 index e4a68b1e960..00000000000 --- a/build/node_modules/sax/test/parser-position.js +++ /dev/null @@ -1,28 +0,0 @@ -var sax = require("../lib/sax"), - assert = require("assert") - -function testPosition(chunks, expectedEvents) { - var parser = sax.parser(); - expectedEvents.forEach(function(expectation) { - parser['on' + expectation[0]] = function() { - for (var prop in expectation[1]) { - assert.equal(parser[prop], expectation[1][prop]); - } - } - }); - chunks.forEach(function(chunk) { - parser.write(chunk); - }); -}; - -testPosition(['

      abcdefgh
      '], - [ ['opentag', { position: 5, startTagPosition: 1 }] - , ['text', { position: 19, startTagPosition: 14 }] - , ['closetag', { position: 19, startTagPosition: 14 }] - ]); - -testPosition(['
      abcde','fgh
      '], - [ ['opentag', { position: 5, startTagPosition: 1 }] - , ['text', { position: 19, startTagPosition: 14 }] - , ['closetag', { position: 19, startTagPosition: 14 }] - ]); diff --git a/build/node_modules/sax/test/script-close-better.js b/build/node_modules/sax/test/script-close-better.js deleted file mode 100644 index f4887b9a053..00000000000 --- a/build/node_modules/sax/test/script-close-better.js +++ /dev/null @@ -1,12 +0,0 @@ -require(__dirname).test({ - xml : "", - expect : [ - ["opentag", {"name": "HTML","attributes": {}, isSelfClosing: false}], - ["opentag", {"name": "HEAD","attributes": {}, isSelfClosing: false}], - ["opentag", {"name": "SCRIPT","attributes": {}, isSelfClosing: false}], - ["script", "'
      foo
      ", - expect : [ - ["opentag", {"name": "HTML","attributes": {}, "isSelfClosing": false}], - ["opentag", {"name": "HEAD","attributes": {}, "isSelfClosing": false}], - ["opentag", {"name": "SCRIPT","attributes": {}, "isSelfClosing": false}], - ["script", "if (1 < 0) { console.log('elo there'); }"], - ["closetag", "SCRIPT"], - ["closetag", "HEAD"], - ["closetag", "HTML"] - ] -}); diff --git a/build/node_modules/sax/test/self-closing-child-strict.js b/build/node_modules/sax/test/self-closing-child-strict.js deleted file mode 100644 index 3d6e98520d8..00000000000 --- a/build/node_modules/sax/test/self-closing-child-strict.js +++ /dev/null @@ -1,44 +0,0 @@ - -require(__dirname).test({ - xml : - ""+ - "" + - "" + - "" + - "" + - "=(|)" + - "" + - "", - expect : [ - ["opentag", { - "name": "root", - "attributes": {}, - "isSelfClosing": false - }], - ["opentag", { - "name": "child", - "attributes": {}, - "isSelfClosing": false - }], - ["opentag", { - "name": "haha", - "attributes": {}, - "isSelfClosing": true - }], - ["closetag", "haha"], - ["closetag", "child"], - ["opentag", { - "name": "monkey", - "attributes": {}, - "isSelfClosing": false - }], - ["text", "=(|)"], - ["closetag", "monkey"], - ["closetag", "root"], - ["end"], - ["ready"] - ], - strict : true, - opt : {} -}); - diff --git a/build/node_modules/sax/test/self-closing-child.js b/build/node_modules/sax/test/self-closing-child.js deleted file mode 100644 index f31c36646cc..00000000000 --- a/build/node_modules/sax/test/self-closing-child.js +++ /dev/null @@ -1,44 +0,0 @@ - -require(__dirname).test({ - xml : - ""+ - "" + - "" + - "" + - "" + - "=(|)" + - "" + - "", - expect : [ - ["opentag", { - "name": "ROOT", - "attributes": {}, - "isSelfClosing": false - }], - ["opentag", { - "name": "CHILD", - "attributes": {}, - "isSelfClosing": false - }], - ["opentag", { - "name": "HAHA", - "attributes": {}, - "isSelfClosing": true - }], - ["closetag", "HAHA"], - ["closetag", "CHILD"], - ["opentag", { - "name": "MONKEY", - "attributes": {}, - "isSelfClosing": false - }], - ["text", "=(|)"], - ["closetag", "MONKEY"], - ["closetag", "ROOT"], - ["end"], - ["ready"] - ], - strict : false, - opt : {} -}); - diff --git a/build/node_modules/sax/test/self-closing-tag.js b/build/node_modules/sax/test/self-closing-tag.js deleted file mode 100644 index d1d8b7c828c..00000000000 --- a/build/node_modules/sax/test/self-closing-tag.js +++ /dev/null @@ -1,25 +0,0 @@ - -require(__dirname).test({ - xml : - " "+ - " "+ - " "+ - " "+ - "=(|) "+ - ""+ - " ", - expect : [ - ["opentag", {name:"ROOT", attributes:{}, isSelfClosing: false}], - ["opentag", {name:"HAHA", attributes:{}, isSelfClosing: true}], - ["closetag", "HAHA"], - ["opentag", {name:"HAHA", attributes:{}, isSelfClosing: true}], - ["closetag", "HAHA"], - // ["opentag", {name:"HAHA", attributes:{}}], - // ["closetag", "HAHA"], - ["opentag", {name:"MONKEY", attributes:{}, isSelfClosing: false}], - ["text", "=(|)"], - ["closetag", "MONKEY"], - ["closetag", "ROOT"] - ], - opt : { trim : true } -}); \ No newline at end of file diff --git a/build/node_modules/sax/test/stray-ending.js b/build/node_modules/sax/test/stray-ending.js deleted file mode 100644 index bec467b2267..00000000000 --- a/build/node_modules/sax/test/stray-ending.js +++ /dev/null @@ -1,17 +0,0 @@ -// stray ending tags should just be ignored in non-strict mode. -// https://github.com/isaacs/sax-js/issues/32 -require(__dirname).test - ( { xml : - "" - , expect : - [ [ "opentag", { name: "A", attributes: {}, isSelfClosing: false } ] - , [ "opentag", { name: "B", attributes: {}, isSelfClosing: false } ] - , [ "text", "" ] - , [ "closetag", "B" ] - , [ "closetag", "A" ] - ] - , strict : false - , opt : {} - } - ) - diff --git a/build/node_modules/sax/test/trailing-attribute-no-value.js b/build/node_modules/sax/test/trailing-attribute-no-value.js deleted file mode 100644 index 222837f8f9d..00000000000 --- a/build/node_modules/sax/test/trailing-attribute-no-value.js +++ /dev/null @@ -1,10 +0,0 @@ - -require(__dirname).test({ - xml : - "", - expect : [ - ["attribute", {name:"ATTRIB", value:"attrib"}], - ["opentag", {name:"ROOT", attributes:{"ATTRIB":"attrib"}, isSelfClosing: false}] - ], - opt : { trim : true } -}); diff --git a/build/node_modules/sax/test/trailing-non-whitespace.js b/build/node_modules/sax/test/trailing-non-whitespace.js deleted file mode 100644 index 619578b1773..00000000000 --- a/build/node_modules/sax/test/trailing-non-whitespace.js +++ /dev/null @@ -1,18 +0,0 @@ - -require(__dirname).test({ - xml : "Welcome, to monkey land", - expect : [ - ["opentag", { - "name": "SPAN", - "attributes": {}, - isSelfClosing: false - }], - ["text", "Welcome,"], - ["closetag", "SPAN"], - ["text", " to monkey land"], - ["end"], - ["ready"] - ], - strict : false, - opt : {} -}); diff --git a/build/node_modules/sax/test/unclosed-root.js b/build/node_modules/sax/test/unclosed-root.js deleted file mode 100644 index f4eeac61b31..00000000000 --- a/build/node_modules/sax/test/unclosed-root.js +++ /dev/null @@ -1,11 +0,0 @@ -require(__dirname).test - ( { xml : "" - - , expect : - [ [ "opentag", { name: "root", attributes: {}, isSelfClosing: false } ] - , [ "error", "Unclosed root tag\nLine: 0\nColumn: 6\nChar: " ] - ] - , strict : true - , opt : {} - } - ) diff --git a/build/node_modules/sax/test/unquoted.js b/build/node_modules/sax/test/unquoted.js deleted file mode 100644 index b3a9a8122e8..00000000000 --- a/build/node_modules/sax/test/unquoted.js +++ /dev/null @@ -1,18 +0,0 @@ -// unquoted attributes should be ok in non-strict mode -// https://github.com/isaacs/sax-js/issues/31 -require(__dirname).test - ( { xml : - "" - , expect : - [ [ "attribute", { name: "CLASS", value: "test" } ] - , [ "attribute", { name: "HELLO", value: "world" } ] - , [ "opentag", { name: "SPAN", - attributes: { CLASS: "test", HELLO: "world" }, - isSelfClosing: false } ] - , [ "closetag", "SPAN" ] - ] - , strict : false - , opt : {} - } - ) - diff --git a/build/node_modules/sax/test/utf8-split.js b/build/node_modules/sax/test/utf8-split.js deleted file mode 100644 index e22bc100443..00000000000 --- a/build/node_modules/sax/test/utf8-split.js +++ /dev/null @@ -1,32 +0,0 @@ -var assert = require('assert') -var saxStream = require('../lib/sax').createStream() - -var b = new Buffer('误') - -saxStream.on('text', function(text) { - assert.equal(text, b.toString()) -}) - -saxStream.write(new Buffer('')) -saxStream.write(b.slice(0, 1)) -saxStream.write(b.slice(1)) -saxStream.write(new Buffer('')) -saxStream.write(b.slice(0, 2)) -saxStream.write(b.slice(2)) -saxStream.write(new Buffer('')) -saxStream.write(b) -saxStream.write(new Buffer('')) -saxStream.write(Buffer.concat([new Buffer(''), b.slice(0, 1)])) -saxStream.end(Buffer.concat([b.slice(1), new Buffer('')])) - -var saxStream2 = require('../lib/sax').createStream() - -saxStream2.on('text', function(text) { - assert.equal(text, '�') -}); - -saxStream2.write(new Buffer('')); -saxStream2.write(new Buffer([0xC0])); -saxStream2.write(new Buffer('')); -saxStream2.write(Buffer.concat([new Buffer(''), b.slice(0,1)])); -saxStream2.end(); diff --git a/build/node_modules/sax/test/xmlns-issue-41.js b/build/node_modules/sax/test/xmlns-issue-41.js deleted file mode 100644 index 17ab45a0fb7..00000000000 --- a/build/node_modules/sax/test/xmlns-issue-41.js +++ /dev/null @@ -1,68 +0,0 @@ -var t = require(__dirname) - - , xmls = // should be the same both ways. - [ "" - , "" ] - - , ex1 = - [ [ "opennamespace" - , { prefix: "a" - , uri: "http://ATTRIBUTE" - } - ] - , [ "attribute" - , { name: "xmlns:a" - , value: "http://ATTRIBUTE" - , prefix: "xmlns" - , local: "a" - , uri: "http://www.w3.org/2000/xmlns/" - } - ] - , [ "attribute" - , { name: "a:attr" - , local: "attr" - , prefix: "a" - , uri: "http://ATTRIBUTE" - , value: "value" - } - ] - , [ "opentag" - , { name: "parent" - , uri: "" - , prefix: "" - , local: "parent" - , attributes: - { "a:attr": - { name: "a:attr" - , local: "attr" - , prefix: "a" - , uri: "http://ATTRIBUTE" - , value: "value" - } - , "xmlns:a": - { name: "xmlns:a" - , local: "a" - , prefix: "xmlns" - , uri: "http://www.w3.org/2000/xmlns/" - , value: "http://ATTRIBUTE" - } - } - , ns: {"a": "http://ATTRIBUTE"} - , isSelfClosing: true - } - ] - , ["closetag", "parent"] - , ["closenamespace", { prefix: "a", uri: "http://ATTRIBUTE" }] - ] - - // swap the order of elements 2 and 1 - , ex2 = [ex1[0], ex1[2], ex1[1]].concat(ex1.slice(3)) - , expected = [ex1, ex2] - -xmls.forEach(function (x, i) { - t.test({ xml: x - , expect: expected[i] - , strict: true - , opt: { xmlns: true } - }) -}) diff --git a/build/node_modules/sax/test/xmlns-rebinding.js b/build/node_modules/sax/test/xmlns-rebinding.js deleted file mode 100644 index 07e04255390..00000000000 --- a/build/node_modules/sax/test/xmlns-rebinding.js +++ /dev/null @@ -1,63 +0,0 @@ - -require(__dirname).test - ( { xml : - ""+ - ""+ - ""+ - ""+ - ""+ - "" - - , expect : - [ [ "opennamespace", { prefix: "x", uri: "x1" } ] - , [ "opennamespace", { prefix: "y", uri: "y1" } ] - , [ "attribute", { name: "xmlns:x", value: "x1", uri: "http://www.w3.org/2000/xmlns/", prefix: "xmlns", local: "x" } ] - , [ "attribute", { name: "xmlns:y", value: "y1", uri: "http://www.w3.org/2000/xmlns/", prefix: "xmlns", local: "y" } ] - , [ "attribute", { name: "x:a", value: "x1", uri: "x1", prefix: "x", local: "a" } ] - , [ "attribute", { name: "y:a", value: "y1", uri: "y1", prefix: "y", local: "a" } ] - , [ "opentag", { name: "root", uri: "", prefix: "", local: "root", - attributes: { "xmlns:x": { name: "xmlns:x", value: "x1", uri: "http://www.w3.org/2000/xmlns/", prefix: "xmlns", local: "x" } - , "xmlns:y": { name: "xmlns:y", value: "y1", uri: "http://www.w3.org/2000/xmlns/", prefix: "xmlns", local: "y" } - , "x:a": { name: "x:a", value: "x1", uri: "x1", prefix: "x", local: "a" } - , "y:a": { name: "y:a", value: "y1", uri: "y1", prefix: "y", local: "a" } }, - ns: { x: 'x1', y: 'y1' }, - isSelfClosing: false } ] - - , [ "opennamespace", { prefix: "x", uri: "x2" } ] - , [ "attribute", { name: "xmlns:x", value: "x2", uri: "http://www.w3.org/2000/xmlns/", prefix: "xmlns", local: "x" } ] - , [ "opentag", { name: "rebind", uri: "", prefix: "", local: "rebind", - attributes: { "xmlns:x": { name: "xmlns:x", value: "x2", uri: "http://www.w3.org/2000/xmlns/", prefix: "xmlns", local: "x" } }, - ns: { x: 'x2' }, - isSelfClosing: false } ] - - , [ "attribute", { name: "x:a", value: "x2", uri: "x2", prefix: "x", local: "a" } ] - , [ "attribute", { name: "y:a", value: "y1", uri: "y1", prefix: "y", local: "a" } ] - , [ "opentag", { name: "check", uri: "", prefix: "", local: "check", - attributes: { "x:a": { name: "x:a", value: "x2", uri: "x2", prefix: "x", local: "a" } - , "y:a": { name: "y:a", value: "y1", uri: "y1", prefix: "y", local: "a" } }, - ns: { x: 'x2' }, - isSelfClosing: true } ] - - , [ "closetag", "check" ] - - , [ "closetag", "rebind" ] - , [ "closenamespace", { prefix: "x", uri: "x2" } ] - - , [ "attribute", { name: "x:a", value: "x1", uri: "x1", prefix: "x", local: "a" } ] - , [ "attribute", { name: "y:a", value: "y1", uri: "y1", prefix: "y", local: "a" } ] - , [ "opentag", { name: "check", uri: "", prefix: "", local: "check", - attributes: { "x:a": { name: "x:a", value: "x1", uri: "x1", prefix: "x", local: "a" } - , "y:a": { name: "y:a", value: "y1", uri: "y1", prefix: "y", local: "a" } }, - ns: { x: 'x1', y: 'y1' }, - isSelfClosing: true } ] - , [ "closetag", "check" ] - - , [ "closetag", "root" ] - , [ "closenamespace", { prefix: "x", uri: "x1" } ] - , [ "closenamespace", { prefix: "y", uri: "y1" } ] - ] - , strict : true - , opt : { xmlns: true } - } - ) - diff --git a/build/node_modules/sax/test/xmlns-strict.js b/build/node_modules/sax/test/xmlns-strict.js deleted file mode 100644 index b5e3e518868..00000000000 --- a/build/node_modules/sax/test/xmlns-strict.js +++ /dev/null @@ -1,74 +0,0 @@ - -require(__dirname).test - ( { xml : - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - ""+ - "" - - , expect : - [ [ "opentag", { name: "root", prefix: "", local: "root", uri: "", - attributes: {}, ns: {}, isSelfClosing: false } ] - - , [ "attribute", { name: "attr", value: "normal", prefix: "", local: "attr", uri: "" } ] - , [ "opentag", { name: "plain", prefix: "", local: "plain", uri: "", - attributes: { "attr": { name: "attr", value: "normal", uri: "", prefix: "", local: "attr", uri: "" } }, - ns: {}, isSelfClosing: true } ] - , [ "closetag", "plain" ] - - , [ "opennamespace", { prefix: "", uri: "uri:default" } ] - - , [ "attribute", { name: "xmlns", value: "uri:default", prefix: "xmlns", local: "", uri: "http://www.w3.org/2000/xmlns/" } ] - , [ "opentag", { name: "ns1", prefix: "", local: "ns1", uri: "uri:default", - attributes: { "xmlns": { name: "xmlns", value: "uri:default", prefix: "xmlns", local: "", uri: "http://www.w3.org/2000/xmlns/" } }, - ns: { "": "uri:default" }, isSelfClosing: false } ] - - , [ "attribute", { name: "attr", value: "normal", prefix: "", local: "attr", uri: "" } ] - , [ "opentag", { name: "plain", prefix: "", local: "plain", uri: "uri:default", ns: { '': 'uri:default' }, - attributes: { "attr": { name: "attr", value: "normal", prefix: "", local: "attr", uri: "" } }, - isSelfClosing: true } ] - , [ "closetag", "plain" ] - - , [ "closetag", "ns1" ] - - , [ "closenamespace", { prefix: "", uri: "uri:default" } ] - - , [ "opennamespace", { prefix: "a", uri: "uri:nsa" } ] - - , [ "attribute", { name: "xmlns:a", value: "uri:nsa", prefix: "xmlns", local: "a", uri: "http://www.w3.org/2000/xmlns/" } ] - - , [ "opentag", { name: "ns2", prefix: "", local: "ns2", uri: "", - attributes: { "xmlns:a": { name: "xmlns:a", value: "uri:nsa", prefix: "xmlns", local: "a", uri: "http://www.w3.org/2000/xmlns/" } }, - ns: { a: "uri:nsa" }, isSelfClosing: false } ] - - , [ "attribute", { name: "attr", value: "normal", prefix: "", local: "attr", uri: "" } ] - , [ "opentag", { name: "plain", prefix: "", local: "plain", uri: "", - attributes: { "attr": { name: "attr", value: "normal", prefix: "", local: "attr", uri: "" } }, - ns: { a: 'uri:nsa' }, - isSelfClosing: true } ] - , [ "closetag", "plain" ] - - , [ "attribute", { name: "a:attr", value: "namespaced", prefix: "a", local: "attr", uri: "uri:nsa" } ] - , [ "opentag", { name: "a:ns", prefix: "a", local: "ns", uri: "uri:nsa", - attributes: { "a:attr": { name: "a:attr", value: "namespaced", prefix: "a", local: "attr", uri: "uri:nsa" } }, - ns: { a: 'uri:nsa' }, - isSelfClosing: true } ] - , [ "closetag", "a:ns" ] - - , [ "closetag", "ns2" ] - - , [ "closenamespace", { prefix: "a", uri: "uri:nsa" } ] - - , [ "closetag", "root" ] - ] - , strict : true - , opt : { xmlns: true } - } - ) - diff --git a/build/node_modules/sax/test/xmlns-unbound-element.js b/build/node_modules/sax/test/xmlns-unbound-element.js deleted file mode 100644 index 9d031a2bdad..00000000000 --- a/build/node_modules/sax/test/xmlns-unbound-element.js +++ /dev/null @@ -1,33 +0,0 @@ -require(__dirname).test( - { strict : true - , opt : { xmlns: true } - , expect : - [ [ "error", "Unbound namespace prefix: \"unbound:root\"\nLine: 0\nColumn: 15\nChar: >"] - , [ "opentag", { name: "unbound:root", uri: "unbound", prefix: "unbound", local: "root" - , attributes: {}, ns: {}, isSelfClosing: true } ] - , [ "closetag", "unbound:root" ] - ] - } -).write(""); - -require(__dirname).test( - { strict : true - , opt : { xmlns: true } - , expect : - [ [ "opennamespace", { prefix: "unbound", uri: "someuri" } ] - , [ "attribute", { name: 'xmlns:unbound', value: 'someuri' - , prefix: 'xmlns', local: 'unbound' - , uri: 'http://www.w3.org/2000/xmlns/' } ] - , [ "opentag", { name: "unbound:root", uri: "someuri", prefix: "unbound", local: "root" - , attributes: { 'xmlns:unbound': { - name: 'xmlns:unbound' - , value: 'someuri' - , prefix: 'xmlns' - , local: 'unbound' - , uri: 'http://www.w3.org/2000/xmlns/' } } - , ns: { "unbound": "someuri" }, isSelfClosing: true } ] - , [ "closetag", "unbound:root" ] - , [ "closenamespace", { prefix: 'unbound', uri: 'someuri' }] - ] - } -).write(""); diff --git a/build/node_modules/sax/test/xmlns-unbound.js b/build/node_modules/sax/test/xmlns-unbound.js deleted file mode 100644 index b740e26124d..00000000000 --- a/build/node_modules/sax/test/xmlns-unbound.js +++ /dev/null @@ -1,15 +0,0 @@ - -require(__dirname).test( - { strict : true - , opt : { xmlns: true } - , expect : - [ ["error", "Unbound namespace prefix: \"unbound\"\nLine: 0\nColumn: 28\nChar: >"] - - , [ "attribute", { name: "unbound:attr", value: "value", uri: "unbound", prefix: "unbound", local: "attr" } ] - , [ "opentag", { name: "root", uri: "", prefix: "", local: "root", - attributes: { "unbound:attr": { name: "unbound:attr", value: "value", uri: "unbound", prefix: "unbound", local: "attr" } }, - ns: {}, isSelfClosing: true } ] - , [ "closetag", "root" ] - ] - } -).write("") diff --git a/build/node_modules/sax/test/xmlns-xml-default-ns.js b/build/node_modules/sax/test/xmlns-xml-default-ns.js deleted file mode 100644 index b1984d25509..00000000000 --- a/build/node_modules/sax/test/xmlns-xml-default-ns.js +++ /dev/null @@ -1,31 +0,0 @@ -var xmlns_attr = -{ - name: "xmlns", value: "http://foo", prefix: "xmlns", - local: "", uri : "http://www.w3.org/2000/xmlns/" -}; - -var attr_attr = -{ - name: "attr", value: "bar", prefix: "", - local : "attr", uri : "" -}; - - -require(__dirname).test - ( { xml : - "" - , expect : - [ [ "opennamespace", { prefix: "", uri: "http://foo" } ] - , [ "attribute", xmlns_attr ] - , [ "attribute", attr_attr ] - , [ "opentag", { name: "elm", prefix: "", local: "elm", uri : "http://foo", - ns : { "" : "http://foo" }, - attributes: { xmlns: xmlns_attr, attr: attr_attr }, - isSelfClosing: true } ] - , [ "closetag", "elm" ] - , [ "closenamespace", { prefix: "", uri: "http://foo"} ] - ] - , strict : true - , opt : {xmlns: true} - } - ) diff --git a/build/node_modules/sax/test/xmlns-xml-default-prefix-attribute.js b/build/node_modules/sax/test/xmlns-xml-default-prefix-attribute.js deleted file mode 100644 index e41f21875e4..00000000000 --- a/build/node_modules/sax/test/xmlns-xml-default-prefix-attribute.js +++ /dev/null @@ -1,36 +0,0 @@ -require(__dirname).test( - { xml : "" - , expect : - [ [ "attribute" - , { name: "xml:lang" - , local: "lang" - , prefix: "xml" - , uri: "http://www.w3.org/XML/1998/namespace" - , value: "en" - } - ] - , [ "opentag" - , { name: "root" - , uri: "" - , prefix: "" - , local: "root" - , attributes: - { "xml:lang": - { name: "xml:lang" - , local: "lang" - , prefix: "xml" - , uri: "http://www.w3.org/XML/1998/namespace" - , value: "en" - } - } - , ns: {} - , isSelfClosing: true - } - ] - , ["closetag", "root"] - ] - , strict : true - , opt : { xmlns: true } - } -) - diff --git a/build/node_modules/sax/test/xmlns-xml-default-prefix.js b/build/node_modules/sax/test/xmlns-xml-default-prefix.js deleted file mode 100644 index a85b4787f21..00000000000 --- a/build/node_modules/sax/test/xmlns-xml-default-prefix.js +++ /dev/null @@ -1,21 +0,0 @@ -require(__dirname).test( - { xml : "" - , expect : - [ - [ "opentag" - , { name: "xml:root" - , uri: "http://www.w3.org/XML/1998/namespace" - , prefix: "xml" - , local: "root" - , attributes: {} - , ns: {} - , isSelfClosing: true - } - ] - , ["closetag", "xml:root"] - ] - , strict : true - , opt : { xmlns: true } - } -) - diff --git a/build/node_modules/sax/test/xmlns-xml-default-redefine.js b/build/node_modules/sax/test/xmlns-xml-default-redefine.js deleted file mode 100644 index d35d5a0cbe2..00000000000 --- a/build/node_modules/sax/test/xmlns-xml-default-redefine.js +++ /dev/null @@ -1,41 +0,0 @@ -require(__dirname).test( - { xml : "" - , expect : - [ ["error" - , "xml: prefix must be bound to http://www.w3.org/XML/1998/namespace\n" - + "Actual: ERROR\n" - + "Line: 0\nColumn: 27\nChar: '" - ] - , [ "attribute" - , { name: "xmlns:xml" - , local: "xml" - , prefix: "xmlns" - , uri: "http://www.w3.org/2000/xmlns/" - , value: "ERROR" - } - ] - , [ "opentag" - , { name: "xml:root" - , uri: "http://www.w3.org/XML/1998/namespace" - , prefix: "xml" - , local: "root" - , attributes: - { "xmlns:xml": - { name: "xmlns:xml" - , local: "xml" - , prefix: "xmlns" - , uri: "http://www.w3.org/2000/xmlns/" - , value: "ERROR" - } - } - , ns: {} - , isSelfClosing: true - } - ] - , ["closetag", "xml:root"] - ] - , strict : true - , opt : { xmlns: true } - } -) - diff --git a/build/vswhere.exe b/build/vswhere.exe new file mode 100644 index 00000000000..1731aa6ed27 Binary files /dev/null and b/build/vswhere.exe differ diff --git a/docs/2014/release-notes.md b/docs/2014/release-notes.md deleted file mode 100644 index 6e37409f465..00000000000 --- a/docs/2014/release-notes.md +++ /dev/null @@ -1,5666 +0,0 @@ -## Go to [2015 Release Notes](https://github.com/ServiceStack/ServiceStack/blob/master/docs/2015/release-notes.md) - ---- - -# v4.0.35 Release Notes - -We're ending 2014 with a short release cycle primarily focused on a polished and fixes Release, ready for before everyone gets back at work - re-energized for a Happy New 2015 work year :) - -## New [TechStacks](http://techstacks.io) LiveDemo! - -We've been gradually refining our modern [AngularJS](https://github.com/ServiceStack/ServiceStackVS/blob/master/docs/angular-spa.md) and [React](https://github.com/ServiceStackApps/Chat-React) Single Page App VS.NET templates which represents what we believe to be the optimal formula for developing future .NET-based JS Apps - utilizing a best-of-breed node.js, npm, bower, grunt/gulp build system. - -To this end we're developing new Single Page Apps alongside to further refine these VS.NET templates and demonstrate their potential in using the pre-configured Grunt tasks to manage the full iterative client/server building, optimization and deployment dev workflows. - -We're happy to be able to preview the latest Live Demo built on the **AngularJS App** VS.NET template in: http://techstacks.io - -[![TechStacks](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/techstacks/screenshots/techstacks.png)](http://techstacks.io) - -TechStacks is a modern [AngularJS](https://angularjs.org/) CRUD App that lets you Browse and Add Technology Stacks of popular StartUps. After Signing in you can add your own TechStacks and favorite technologies to create a personalized custom 'feed' to view Websites and Apps built with your favorite programming languages and technologies. - -TechStacks is based on a [Bootstrap template](http://getbootstrap.com) with client-side features: - - - HTML5 Routing to enable pretty urls, also supports full page reloads and back button support - - Same Services supporting both human-readable Slugs or int primary keys - - Responsive design supporting iPad Landscape and Portrait modes - - Preloading and background data fetching to reduce flicker and maximize responsiveness - - [Disqus](https://disqus.com/) commenting system - - [Chosen](http://harvesthq.github.io/chosen/) for UX-friendly multi combo boxes - -and some of TechStacks back-end features include: - - - [Twitter and GitHub OAuth Providers](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization) - - Substitutable [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) RDBMS [PostgreSQL and Sqlite](https://github.com/ServiceStackApps/TechStacks/blob/875e78910e43d2230f0925b71d5990497216511e/src/TechStacks/TechStacks/AppHost.cs#L49-L56) back-ends - - [Auto Query](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) for automatic services of RDBMS tables - - [RDBMS Sessions and In Memory Caching](https://github.com/ServiceStack/ServiceStack/wiki/Caching) - - [Smart Razor Views](http://razor.servicestack.net) - - [Fluent Validation](https://github.com/ServiceStack/ServiceStack/wiki/Validation) - -TechStacks is a good example of the experience you can get running a packaged ServiceStack/AngularJS App on modest hardware - [techstacks.io](http://techstacks.io) is currently running on a single **m1.small** AWS EC2 instance and **db.t1.micro** RDS PostgreSQL instance that hosts all [Live Demos](https://github.com/ServiceStackApps/LiveDemos). - - - -### [View the Source](https://github.com/ServiceStackApps/TechStacks) - -Checkout the [Source Code for TechStacks](https://github.com/ServiceStackApps/TechStacks) for the full details to see how it's built. The project also includes an [example client layout](https://github.com/ServiceStackApps/TechStacks/tree/master/src/TechStacks/TechStacks/js) for structuring larger AngularJS projects in an extensible layout files and folder structure: - -### HTML5 Routing and Full-page reloads - -One of the disadvantages of Single Page Apps is having to resort to hash-style `#!` url suffix hacks to prevent JavaScript apps from making full-page reloads. By utilizing [AngularJS's HTML5 mode](https://docs.angularjs.org/guide/$location#html5-mode) we can take advantage of modern browsers support for HTML5 History API to retain the optimal pretty urls (we'd have if this were a server generated website) whilst still retaining the responsiveness of JS Apps which are able to load just the minimum content required, i.e. instead of waiting for the full page rendering of Server generated pages and their resource dependencies to be loaded again. - -ServiceStack has great support for these modern-style SPA's which lets you specify a fallback handler for **HTML page requests** with un-matched routes to return the same `/default.cshtml` home page so AngularJS is able to handle the request and perform the same client-side routing it would've had the url been navigated from within the App - using the [AppHost configuration below](https://github.com/ServiceStackApps/TechStacks/blob/41efa5d8add1c4b0bdd449d6507878f2c8387bbc/src/TechStacks/TechStacks/AppHost.cs#L41): - -```csharp -base.CustomErrorHttpHandlers[HttpStatusCode.NotFound] = new RazorHandler("/default.cshtml"); -``` - -This lets you re-use pretty client-side routes like: - - - http://techstacks.io/tech/servicestack - -And allow deep-link support for full round-trip requests (i.e. outside of AngularJS) - where since `/tech/servicestack` doesn't match any custom Server routes, ServiceStack instead responds with the above `/default.cshtml` Razor View. At which point AngularJS takes over and navigates to the internal route mapping that matches `/tech/servicestack`. - -> To get the latest AngularJS and React.js App templates download the latest [ServiceStackVS VS.NET Extension](https://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) - -## ServerEvents now supports Multiple Channels per subscription - -To ensure each Client only ever needs 1 ServerEvents subscription, subscriptions now support subscribing to multiple channels. Multi Channel Support is fully implemented in all [JavaScript ServerEvents](https://github.com/ServiceStack/ServiceStack/wiki/JavaScript-Server-Events-Client) and [C#/.NET ServerEvents](https://github.com/ServiceStack/ServiceStack/wiki/C%23-Server-Events-Client) Clients as well as both [back-end InMemory](https://github.com/ServiceStack/ServiceStack/wiki/Server-Events) and [Redis ServerEvents](https://github.com/ServiceStack/ServiceStack/wiki/Redis-Server-Events) providers. - -The API remains similar to the previous Single Channel Routes where in addition to subscribing to a single channel: - - /event-stream?channel=Home - -Clients can also subscribe to multiple channels: - - /event-stream?channel=Home,Work,Play - -> If preferred, clients can also use the more readable **?channels=** plural variable name - -And the above example again using the [C#/.NET ServerEvents Client](https://github.com/ServiceStack/ServiceStack/wiki/C%23-Server-Events-Client): - -```csharp -var client = new ServerEventsClient(BaseUri, "Home"); - -var client = new ServerEventsClient(BaseUri, "Home", "Work", "Play"); -``` - -Multi-Channel subscriptions works conceptually similar to having multiple "single channel" subscriptions where multiple Join/Leave/Message events are fired for events occurring in each channel. For more details on this checkout the [multi-channel ServerEvents tests](https://github.com/ServiceStack/ServiceStack/blob/42d08dee1f4945f1a7be29ac234ce1250e04de9b/tests/ServiceStack.WebHost.Endpoints.Tests/ServerEventTests.cs#L781). - -### Chat Apps now support multiple Chat Rooms - -With this feature, we can now create Chat Apps that support multiple Chat Rooms using only a single ServerEvents subscription: - -[![React Multi-Channel Chat](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/chat-react-multichannels.png)](http://react-chat.servicestack.net/?channels=home,work,play) - -> Multi-Channel React Chat preview - -Surprisingly it only took a small amount of code to add support for multiple chat rooms in all the different Chat Apps which now all support Multiple Chat rooms: - - - Upgrade [jQuery Chat Client/Server](https://github.com/ServiceStackApps/Chat/commit/f23bb912791425abcba1bc724cd86cb4ab8cac82) to support multiple Chat Rooms - - Upgrade [React Chat Client](https://github.com/ServiceStackApps/Chat-React/commit/8969ce9c291d88f63d84500b3bb281c3b1f451c7) to support multiple Chat Rooms - - Upgrade [React Chat Server](https://github.com/ServiceStackApps/Chat-React/commit/cae43b6923771b02c28726dcfa4927d8490275ee) to support multiple Chat Rooms - - Upgrade [ServiceStack.Gap Chat Client/Server](https://github.com/ServiceStack/ServiceStack.Gap/commit/6ee72d81fcf7cd73573b686400500d7516f312b9) to support multiple Chat Rooms - -Should you want to run the previous "Single Room" Chat Apps, they're available in the **single-channel** branches: - - - [jQuery Chat](https://github.com/ServiceStackApps/Chat/tree/single-channel) - - [React Chat](https://github.com/ServiceStackApps/Chat-React/tree/singe-channel) - -> Multi-Channel support is mostly backwards compatible where all Chat Apps can be run as-is when upgraded to use the latest ServiceStack v4.0.35+ - but it does require upgrading both v4.0.35 Client and Server libraries together. - -## Minor Changes and Fixes - -Rest of this release was focused on minor features, changes and fixes: - -### Framework Changes - - - Custom HTTP Handlers now execute Global Request Filters [709fb73](https://github.com/ServiceStack/ServiceStack/commit/709fb73c1450f13ba6449eed9101e588775c3d9d) - - Static Default html pages (e.g. default.html) are served directly from root instead of being redirected to static file - Behavior is now in-line with `default.cshtml` in Razor Support [5b5d7fa](https://github.com/ServiceStack/ServiceStack/commit/5b5d7fa66bbd3d4237ede8a5bc9054354dfa7b2c) - - StaticFileHandler HTTP Handler is now re-usable `VirtualNode` for returning Static Files [8571ecd](https://github.com/ServiceStack/ServiceStack/commit/8571ecd6f7e244ee152e959e6759f6a1ee82fe4d) - - Original C#/.NET Exception is now accessible as `InnerException` in wrapped `HttpError` [42d5976](https://github.com/ServiceStack/ServiceStack/commit/42d59767fd8ea9414470cbedbac8b2bae308e9e8) - - Added overridable `IDbConnectionFactory` and `IRedisClientsManager` properties in `Service` base class [c18215b](https://github.com/ServiceStack/ServiceStack/commit/c18215b58a7a71f9537f8614ce42acf91beaee3b) - - Add `.woff2` to `Config.AllowFileExtensions` white-list [aa1e93a](https://github.com/ServiceStack/ServiceStack/commit/aa1e93adcea85216aac807cad4bdbe8f71ff2f52) - - Changed all methods in MVC ServiceStackController base class to protected to prevent MVC Controller Factories from assuming their MVC Actions [eff11c](https://github.com/ServiceStack/ServiceStack/commit/eff11c8992df78b18b07cc0137d27ea1e2d7eb47) - - Added Remove Plugin and Debug Link API's [9002d48](https://github.com/ServiceStack/ServiceStack/commit/9002d4827c43dd91e02b298a3b5a56e6e376963a) - - Added Retry logic on Concurrent Update collisions in `OrmLiteCacheClient` [aa6d62c](https://github.com/ServiceStack/ServiceStack/commit/aa6d62ca23ebef30eb3727f3894d214d320843b0) - - Added Runtime Attribute Filter example [355365b](https://github.com/ServiceStack/ServiceStack/commit/355365bbfc45e1309fa2d91fcbc1856e874a9676) - - Add support for implicit querying of enums in AutoQuery [b5d2477](https://github.com/ServiceStack/ServiceStack/commit/b5d2477c581152168f43017a355cbcae9dccbefb) - - Handle Retry Exceptions during on `ServerEventsClient` reconnections [7833cd8](https://github.com/ServiceStack/ServiceStack/commit/7833cd8c25e0eb4dc10cd0e0033d2d156393625a) - - Added `AppHost.GetCurrentRequest()` to allow different AppHosts to return the current HttpContext [7cbadda](https://github.com/ServiceStack/ServiceStack/commit/7cbadda18f5666a4c24a0e49fa1af740afd0fec4) - - Fixed NRE during max pool-size overflow handling in `RedisManagerPool` [c94eedd](https://github.com/ServiceStack/ServiceStack.Redis/commit/c94eedd2e3467a418b290209fdf52b01c0516855) - -### Auth Changes - - - `IAuthRepository.CreateOrMergeAuthSession()` now returns the merged `IUserAuthDetails` [f2383ff](https://github.com/ServiceStack/ServiceStack/commit/f2383fffd390d58d2da55dd47eb2b68110066c51) - - `OnRegistered()` callback now fired for successful first-time OAuth requests (in addition to `/register` Service) - - Added `AppHost.OnSaveSession()` to allow custom logic whenever a User Session is saved to the Cache [002a4eb](https://github.com/ServiceStack/ServiceStack/commit/002a4ebf9ea75e922554148ffa2581be05e2c359) - - New `Dictionary Meta` added to allow custom Auth params on `Authenticate` during Authentication [4d339c1](https://github.com/ServiceStack/ServiceStack/commit/4d339c190bf086e2639c3373792b9f4547e0851b) - - New `Config.AddRedirectParamsToQueryString` option added to change redirect params to be added to QueryString instead of hash `#` params [fea60fa](https://github.com/ServiceStack/ServiceStack/commit/fea60fa37000ff7603dc15a31b53150d72bae131) - - `NHibernateUserAuthRepository.GetCurrentSession()` is now overridable to customize NH Session Initialization [7249c9a](https://github.com/ServiceStack/ServiceStack/commit/7249c9af8191ec1bdf7b95db0bba607fe5015dc8) - -### MQ Changes - - - Added `QueueNames.IsTempQueue()` API to determine if a MQ name is a Temp Queue even when custom naming conventions are used [c3ee3d0](https://github.com/ServiceStack/ServiceStack/commit/c3ee3d037ec5676a05e0852ea90d0d75f0d25787) - - Pass `IMessageHandler` in custom MQ Error Handlers so Nak's can be sent from same client that received the message [3be2e3f](https://github.com/ServiceStack/ServiceStack/commit/3be2e3f9d3e9340c4993f8eabc8805c2b1325b18) - -### OrmLite Changes - - - `SqlProc` no longer disposes `IDbCommand` before returning it [9e71480](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/9e714808079aa08f8b7b90766ba308279532c08f) - - Fixed `SingleAsync` API to call correct internal API [b23410](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/b234105065b38df5eb18449e2fb8d5173458c269) - - Added support new Multi-Column OrderBy Descending API's [33292ef](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/33292ef67ec09cbe005afc2cba1f7c417da4434c) - - Add support for `ConvertToList` to handle Scalars as well [4290229](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/4290229cd50ae6475a3edffc198bbdc87cc54539) - -### ServiceStack.Text Changes - - - Add support for Dates in `yyyyMMdd` format [a752f2a](https://github.com/ServiceStack/ServiceStack.Text/commit/a752f2af70f165398899e92b2775daa0d870ff57) - - Add New `DateTimeSerializer.OnParseErrorFn` fallback can be used to handle unknown Date Formats - - Added convenient `Task.Success()` and `Task.Error()` extension methods for non-generic `Task` [b17866a](https://github.com/ServiceStack/ServiceStack.Text/commit/b17866a3b46e3e6c699c20b7f33ef3738fdffd46) - - PCL version of `GetPublicProperties()` now only return instance (non-static) properties [dbe1f83](https://github.com/ServiceStack/ServiceStack.Text/commit/dbe1f8349600ba47e2c4aaaa49c4759198a6ac1f) - -### Dependencies Updated - - - FacebookAuthProvider upgraded to use v2.0 of Facebook's API - - Swagger UI updated latest version - - Memcached updated to 0.57 - - FluentNHibernate to 2.0.1.0 - -# v4.0.34 Release Notes - -## [Add TypeScript Reference!](https://github.com/ServiceStack/ServiceStack/wiki/TypeScript-Add-ServiceStack-Reference) - -The next typed client supported in [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) is [TypeScript](http://www.typescriptlang.org/)! - -![Add TypeScript Reference](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackvs/add-typescript-reference.png) - -[TypeScript](http://www.typescriptlang.org/) is a superset of JavaScript that enhances it with an optional type system for annotating JavaScript source code - bringing many of the code-analysis, insights and tooling benefits that we get to enjoy developing in a typed language like C#/VS.NET. We're excited to also be able to bring these benefits to TypeScript Client Apps consuming ServiceStack Services! - -### TypeScript DTO Interface Declarations - -The TypeScript Native Types feature takes a non-invasive approach in that they're made available in the form of a `.d.ts` [TypeScript declaration file](http://www.typescriptlang.org/Handbook#writing-dts-files). TypeScript declarations are pure static type annotations, i.e. they don't generate any code or otherwise have any effect on runtime behavior. This makes them useful as a non-invasive drop-in into existing JavaScript code where it's used to provide type annotations and intelli-sense on existing JavaScript objects, letting you continue using your existing data types and Ajax libraries. - -### TypeScript Reference Example - -Lets walk through a simple example to see how we can use ServiceStack's TypeScript DTO annotations in our JavaScript clients. Firstly we'll need to add a **TypeScript Reference** to the remote ServiceStack Service by **right-clicking** on your project and clicking on `Add > TypeScript Reference...` (as seen in the above screenshot). - -This will import the remote Services dtos into your local project which ends up looking similar to: - -```typescript -/* Options: -Date: 2014-12-08 17:24:02 -Version: 1 -BaseUrl: http://api.example.com - -GlobalNamespace: dtos -//MakePropertiesOptional: True -//AddServiceStackTypes: True -//AddResponseStatus: False -*/ - -declare module dtos -{ - // @Route("/hello") - // @Route("/hello/{Name}") - interface Hello extends IReturn - { - // @Required() - name:string; - title?:string; - } - - interface HelloResponse - { - result?:string; - } - - interface IReturn {} - ... -} -``` - -Initially the single TypeScript module that contains all the DTO definitions will default to the C#/.NET `ServiceModel` namespace, but this can be made more readable in client apps by uncommenting in the header properties: - -`GlobalNamespace: dtos` - -Looking at the types we'll notice the DTO's are just interface type definitions with any .NET attributes added in comments using AtScript's proposed [meta-data annotations format](https://docs.google.com/document/d/11YUzC-1d0V1-Q3V0fQ7KSit97HnZoKVygDxpWzEYW0U/mobilebasic?viewopt=127). This lets you view helpful documentation about your DTO's like the different custom routes available for each Request DTO. - -By default DTO properties are optional but can be made a required field by annotating the .NET property with the `[Required]` attribute or by uncommenting `MakePropertiesOptional: False` in the header comments which instead defaults all properties as required. - -Property names always reflect to match the remote servers JSON Serialization configuration, i.e. will use **camelCase** properties when the `AppHost` is configured with: - -```csharp -JsConfig.EmitCamelCaseNames = true; -``` - -### Referencing TypeScript DTO's - - -Once added to your project, use VS.NET's JavaScript Doc Comments to reference the TypeScript definitions in your `.ts` scripts. The example below shows how to use the above TypeScript definitions to create a typed Request/Response utilizing jQuery's Ajax API to fire off a new Ajax request on every keystroke: - -```html -/// -... - - -
      - - -``` - -Here we're just using a simple inline `createUrl()` function to show how we're creating the url for the **GET** HTTP Request by appending all Request DTO properties to the QueryString, resulting in a HTTP GET Request that looks like: - - /hello?title=Dr&name=World - -There's also a new `$.ss.createUrl()` API in [ss-utils.js](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library) which also handles .NET Route definitions where it will populate any variables in the `/path/{info}` instead of adding them to the `?QueryString`, e.g: - -```typescript -$(document).bindHandlers({ - sayHello: function () { - var request: dtos.Hello = {}; - request.title = "Dr"; - request.name = this.value; - - $.getJSON($.ss.createUrl("/hello/{Name}", request), request, - function (r: dtos.HelloResponse) { - $("#result").html(r.result); - }); - } -}); -``` - -Which results in a HTTP GET request with the expected Url: - - /hello/World?title=Dr - -### [ss-utils.d.ts](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/js/ss-utils.d.ts) - -To coincide with the new TypeScript Reference support, we've also included a TypeScript declaration file for [ss-utils.js](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library). that's also available as an embedded resource in `ServiceStack.dll` at [/js/ss-utils.d.ts](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/js/ss-utils.d.ts). - -### [Upgrade ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) - -To take advantage of **Add TypeScript Reference** feature, [Upgrade or Install ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) VS.NET Extension: - -[![VS.NET Gallery Download](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackvs/vsgallery-download.png)](http://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) - -> If you already have ServiceStackVS installed, uninstall it first from **Tools -> Extensions and Updates...** then in the Extensions dialog find **ServiceStackVS -> Uninstall**. - -## Auto Batched Requests - -One of the best ways to improve performance, efficiency and reduce latency is to minimize the number of network requests required, which is one of the reasons we've always encouraged [Coarse-grained API designs](https://github.com/ServiceStack/ServiceStack/wiki/Why-Servicestack#servicestack-encourages-development-of-message-style-re-usable-and-batch-full-web-services) - which also lend themselves to better encapsulation and re-use. - -Another common use-case that can be improved are clients making multiple requests to the same API, but due to the lack of a better alternative batched API or control over the server implementation, will default to making multiple N+1 web service requests - thanks to ServiceStack's [message-based design](https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services), that better alternative now exists :) - -### All Services now support Batching! - -With the introduction of **Auto Batched Requests** in this release, all ServiceStack Services now include implicit support for batching, automatically, without any additional effort - where multiple requests of the same type can be sent together in a single HTTP Request. - -This is now enabled in all [.NET Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) via the new `SendAll()` and `SendAllOneWay()` API's, e.g: - -```csharp -var client = new JsonServiceClient(BaseUrl); -var requests = new[] -{ - new Request { Id = 1, Name = "Foo" }, - new Request { Id = 2, Name = "Bar" }, - new Request { Id = 3, Name = "Baz" }, -}; - -List responses = client.SendAll(requests); -``` - -The API works as you would expect where multiple requests can be sent together and the Service Client will return a list of all responses in the same order as the requests were sent. - -And on the back-end, your Services are none the wiser, remaining focused on handling a single Request DTO. In the case below the Service does some work then stores the response in Redis before returning it: - -```csharp -public class MyServices : Service -{ - public object Any(Request request) - { - var response = DoWork(request); - Redis.Store(response); - return response; - } -} -``` - -### Request Execution Flow - -From the Service's point of view nothing changes. Request DTO's still get executed one at a time, through all existing filters just as if they we're sent on their own. They're just delivered together within a single HTTP Request, in this case POST'ed as JSON to the `/json/reply/Request[]` [pre-defined route](https://github.com/ServiceStack/ServiceStack/wiki/Routing#pre-defined-routes): - -![Auto Batched Requests](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/auto-batched-requests.png) - -### Custom Batched Requests Implementations - -If a client was previously calling the same API 100 times, the existing overhead of 100 HTTP Requests would be reduced to just **1 HTTP Request** when batched. Although the above Service would still be calling Redis 100 times to store each Response. - -If later this API has become really hot and you want to improve it even further, you can later add a custom implementation that accepts a `Request[]` and it will only get called once, with access to all the Request DTO's together. In this case we can use a custom implementation and take advantage of Redis's own batched API's and reduce this further to 1 Redis operation: - -```csharp -public class MyServices : Service -{ - public object Any(Request request) - { - var response = DoWork(request); - Redis.Store(response); - return response; - } - - public object Any(Request[] requests) - { - var responses = requests.Map(DoWork); - Redis.StoreAll(responses); - return responses; - } -} -``` - -So with this custom implementation we've gone from **100 HTTP Requests + 100 Redis Operations** to **1 HTTP Request + 1 Redis Operation**. - -Another scenario where you may consider using a **Custom Batched Implementation** is if you wanted to execute all requests within a single RDBMS transaction, which with [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) would look something like: - -```csharp -public class MyServices : Service -{ - public object Any(Request request) - { - var response = DoWork(request); - Db.Insert(request); - return response; - } - - public object Any(Request[] requests) - { - using (var trans = Db.OpenTransaction()) - { - var responses = requests.Map(x => Any(x)); - - trans.Commit(); - return responses; - } - } -} -``` - -Just like with normal Batched Requests, Custom Batched implementations are still executed one at a time through all request/response filters, taking advantage of any existing logic/validation. If you instead only wanted multiple Requests to be treated as a single Request through the entire pipeline you can create a new Request DTO that inherits from `List` which then gets treated as a normal Request DTO e, g: - -```csharp -public class Requests : List {} - -public class MyServices : Service -{ - ... - public object Any(Requests requests) - { - var responses = requests.Map(DoWork); - Redis.StoreAll(responses); - return responses; - } -} -``` - -More examples of Auto Batched Requests and its behavior can be found in the [ReplyAllTests suite](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/ReplyAllTests.cs). - -## New [ReactJS App Template](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project)! - -The new ServiceStackVS **ReactJS App** template shares the same approach for developing modern Single Page Apps in VS.NET as the existing [AngularJS App](https://github.com/ServiceStack/ServiceStackVS/blob/master/docs/angular-spa.md) template by leveraging the **node.js** ecosystem for managing all aspects of Client App development utilizing the best-in-class libraries: - - - [npm](https://www.npmjs.org/) to manage node.js dependencies (bower, grunt, gulp) - - [Bower](http://bower.io/) for managing client dependencies (angular, jquery, bootstrap, etc) - - [Grunt](http://gruntjs.com/) as the primary task runner for server, client packaging and deployments - - [Gulp](http://gulpjs.com/) used by Grunt to do the heavy-lifting bundling and minification - -The templates conveniently pre-configures the above libraries into a working out-of-the-box solution, including high-level grunt tasks to take care of the full-dev-cycle of **building**, **packaging** and **deploying** your app: - - - **[01-run-tests](https://github.com/ServiceStack/ServiceStackVS/blob/docs/angular-spa.md#01-run-tests)** - Runs Karma JavaScript Unit Tests - - **[02-package-server](https://github.com/ServiceStack/ServiceStackVS/blob/docs/angular-spa.md#02-package-server)** - Uses msbuild to build the application and copies server artefacts to `/wwwroot` - - **[03-package-client](https://github.com/ServiceStack/ServiceStackVS/blob/docs/angular-spa.md#03-package-client)** - Optimizes and packages the client artefacts for deployment in `/wwwroot` - - **[04-deploy-app](https://github.com/ServiceStack/ServiceStackVS/blob/docs/angular-spa.md#04-deploy-app)** - Uses MS WebDeploy and `/wwwroot_buld/publish/config.json` to deploy app to specified server - -## [React Chat](https://github.com/ServiceStackApps/Chat-React) - -To help to get started with the **ReactJS App** VS.NET template and learn React, we've rewritten [ServiceStack Chat](https://github.com/ServiceStackApps/Chat) ServerEvents demo using [React](http://facebook.github.io/react/): - -[![React Chat](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/chat-react.png)](http://react-chat.servicestack.net) - -> Live Demo: http://react-chat.servicestack.net - -### [Intro to developing apps with React and Reflux](https://github.com/ServiceStackApps/Chat-React) - -The [React Chat GitHub Repository](https://github.com/ServiceStackApps/Chat-React) also includes a guide of Facebook's [React](http://facebook.github.io/react/) library and [Flux pattern](http://facebook.github.io/react/docs/flux-overview.html) and walks through how to use them to put together a React-based App - making use of the scripts in the ServiceStackVS template along the way to optimize, package and deploy React Chat. - -## [Redis](https://github.com/ServiceStack/ServiceStack.Redis) - -### Heartbeats enabled on [RedisPubSubServer](https://github.com/ServiceStack/ServiceStack.Redis#new-managed-pubsub-server) - -`RedisPubServer` now maintains periodic heartbeats with Redis and will auto-reconnect when it detects a connection has dropped. Heartbeats can be disabled by setting `HeartbeatInterval=null`. - -The new heartbeat support should also improve resiliency in components powered by RedisPubServer, including `RedisMqServer` and `RedisServerEvents`. - -### Updated [RedisManagerPool](https://github.com/ServiceStack/ServiceStack.Redis#redismanagerpool) Pooling Behavior - -`RedisManagerPool` is our new streamlined version of `PooledRedisClientManager` with a simplified API courtesy of the configuration moving into the [Redis Connection String](https://github.com/ServiceStack/ServiceStack.Redis#redis-connection-strings). As an new and alternative Pooled Client Manager we've taken the opportunity to tweak the pooling behavior so that any connections required after the maximum Pool size has been reached will be created and disposed outside of the Pool. - -This is different to `PooledRedisClientManager` which imposes a maximum connection limit and when its maximum pool size has been reached will instead block on any new connection requests until the next RedisClient is released back into the pool. If no client became available within `PoolTimeout`, a Pool Timeout exception will be thrown. - -By not being restricted to a maximum pool size, the new pooling behavior in `RedisManagerPool` lets it maintain a smaller connection pool size at the cost of potentially having a higher opened/closed connection count. - -### Redis HTTP [Request Logger](https://github.com/ServiceStack/ServiceStack/wiki/Request-logger) - -A new `RedisRequestLogger` is available in the **ServiceStack.Server** NuGet package to provide an alternative back-end for the [Request Logs Feature](https://github.com/ServiceStack/ServiceStack/wiki/Request-logger) to log HTTP Requests with Redis so they remain available after AppDomain restarts. - -`RequestLogsFeature` can be configured to use the new `RedisRequestLogger` with: - -```csharp -Plugins.Add(new RequestLogsFeature { - RequestLogger = new RedisRequestLogger( - container.Resolve(), capacity:1000) -}); -``` - -## [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) - -### [Multiple Self References](https://github.com/ServiceStack/ServiceStack.OrmLite#multiple-self-references) - -Supports for multiple Self References of the same type has been added where if there are multiple fields containing `[References]` to the same type, OrmLite will fallback to matching properties based on `{PropertyName}Id` property naming convention, e.g: - -```csharp -public class Customer -{ - [AutoIncrement] - public int Id { get; set; } - public string Name { get; set; } - - [References(typeof(CustomerAddress))] - public int? HomeAddressId { get; set; } - - [References(typeof(CustomerAddress))] - public int? WorkAddressId { get; set; } - - [Reference] - public CustomerAddress HomeAddress { get; set; } - - [Reference] - public CustomerAddress WorkAddress { get; set; } -} -``` - -> Self References now also support mixing and matching of property names and DB Alias naming conventions - -### Support for CROSS JOIN's - -New `CrossJoin` API's were added to `SqlExpression` that works similarly to other JOIN's, e.g: - -```csharp -var q = db.From() - .CrossJoin() - .OrderBy(x => x.Id); - -var results = db.Select(q); -``` - -### OpenDbConnectionString() - -A new `OpenDbConnectionString` API was added to open adhoc connection strings using the same `OrmLiteConnectionFactory` and `DialectProvider` instance. This makes creating Multi Tenant DB Factories a little easier, e.g: - -```csharp -public class MultiTenantDbFactory : IDbConnectionFactory -{ - private readonly IDbConnectionFactory dbFactory; - - public MultiTenantDbFactory(IDbConnectionFactory dbFactory) - { - this.dbFactory = dbFactory; - } - - public IDbConnection OpenDbConnection() - { - var tenantId = RequestContext.Instance.Items["TenantId"] as string; - return tenantId != null - ? dbFactory.OpenDbConnectionString(GetConnectionString(tenantId)) - : dbFactory.OpenDbConnection(); - } - - public IDbConnection CreateDbConnection() - { - return dbFactory.CreateDbConnection(); - } -} -``` - -A complete Multi Tenant OrmLite example can be found in [MultiTennantAppHostTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/MultiTennantAppHostTests.cs) - -### Oracle Provider returns to form - -Thanks to [@TroyDycavinu-AI](https://github.com/TroyDycavinu-AI) efforts, the [Oracle OrmLite Provider](http://nuget.org/packages/ServiceStack.OrmLite.Oracle) test suite is back in the green - -## [Razor](http://razor.servicestack.net/) - -### RenderToAction() - -The new `RenderToAction()` method lets you execute a Service in a Razor View and include it's rendered partial view using just a relative Url: - -```csharp -@Html.RenderAction("/products/1") -``` -It also takes an optional view name if you want a different view than the default: - -```csharp -@Html.RenderAction("/products/1", "CustomProductView") -``` - -An alternative approach to include another Services View is with `Html.Partial()` specifying which view and model you want to render: - -```csharp -@Html.Partial("GetProduct", - base.ExecuteService(s => s.Any(new GetProduct { Id = 1 }))) -``` - -Where `ExecuteService` is a shorthand wrapper around using `ResolveService` in a `using` block: - -```csharp -@{ - Response response = null; - using (var service = base.ResolveService()) - { - response = service.Any(new GetProduct { Id = 1 }); - } -} -@Html.Partial("GetProduct", response) -``` - -### Relative Content Partials - -In addition to Shared Razor Views in `/Views` you can now include Partials relative to the containing Razor Content Page: - -```csharp -@Html.Partial("LocalPartial", model) -@Html.Partial("SubDir/NestedPartial", model) -``` - -## [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) - -### Unlimited Custom Table Joins - -AutoQuery now supports joining any number of tables together by annotating the Request DTO with multiple `IJoin<>` interface markers e.g: - -```csharp -public class MyQuery : QueryBase, - IJoin, - IJoin, - IJoin, - //... -{ -} -``` - -## [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) - - - DTO Interfaces are now included in all C#, F#, VB.NET and TypeScript Native Type providers. - - F# developers can specify `GlobalNamespace` in their generated `.dtos.fs` - - -## [Authentication](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization) - -The `RavenDbUserAuthRepository` now supports specialization so it can be used to persist extended custom `UserAuth` and `UserAuthDetails` types, e.g: - -```csharp -public class CustomRavenDbAuthRepository - : RavenDbUserAuthRepository -{ - //... -} -``` - -### [Sessions](https://github.com/ServiceStack/ServiceStack/wiki/Sessions) - -If needed, Sessions can be injected or modified in ASP.NET hosts with: - -```csharp -HttpContext.Current.Items[ServiceExtensions.RequestItemsSessionKey] = - new AuthUserSession { ... }; -``` - -New Session API's added: - - - `IRequest.RemoveSession(sessionId)` - Remove the Session - - `IRequest.GetSessionTimeToLive()` - Time remaining before current Session expires - - `ICacheClient.GetSessionTimeToLive(id)` - Time remaining before specified Session expires - - - -## Other Features - - - SOAP no longer emits the UTF8 BOM by default, overridable in `Config.XmlWriterSettings` - - CORS Support added in Server Events raw HTTP Handlers - - C# Server Events Client auto restarts when Heartbeat has elapsed the Servers `IdleTimeoutMs` - - Added [workaround for supporting Mono with Redis SSL](https://github.com/mono/mono/pull/1399) - - -## Breaking Changes - -### PCL NuGet Packages Merged - -The **ServiceStack.Client.Pcl** and **ServiceStack.Stripe.Pcl** NuGet packages have been merged into the main **ServiceStack.Client** and **ServiceStack.Stripe** NuGet packages and as a result will no longer receive future updates. If you're using them please update your NuGet references. - -### Refactored Redis Client API's - -`IRedisClient.GetTimeToLive()` now returns a `TimeSpan?` will will return: - - `null` if no key exists - - `TimeSpan.MaxValue` if there is no expiry set on the key - - or a `TimeSpan` value with the time remaining before the key is set to expire - - `KeepAliveRetryAfterMs` has been renamed to `WaitBeforeNextRestart` in `RedisPubSubServer` and the classes that use it: `RedisServerEvents` and `RedisMqServer`. - -# v4.0.33 Release Notes - -## OrmLite now supports Async! - -Another [major feature request](http://servicestack.uservoice.com/forums/176786-feature-requests/suggestions/6217167-provider-async-support-for-ormlite) -is ticked off in this release with the new **Async support available in OrmLite!** - -A quick overview of the new Async API's added can be seen in the class diagram below: - -![OrmLite Async APIs](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/ormlite/OrmLiteApiAsync.png) - -Basically most of OrmLite public API's now have async equivalents of the same name and an additional conventional `*Async` suffix. -The Async API's also take an optional `CancellationToken` making converting sync code trivial, where you just need to -add the `Async` suffix and **await** keyword, as can be seen in the -[Customer Orders UseCase upgrade to Async diff](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/c1ce6f0eac99133fc232b263c26c42379d4c5f48) -, e.g: - -Sync: - -```csharp -db.Insert(new Employee { Id = 1, Name = "Employee 1" }); -db.Save(product1, product2); -var customer = db.Single(new { customer.Email }); -``` - -Async: - -```csharp -await db.InsertAsync(new Employee { Id = 1, Name = "Employee 1" }); -await db.SaveAsync(product1, product2); -var customer = await db.SingleAsync(new { customer.Email }); -``` - -> Effectively the only Data Access API's that doesn't have async equivalents are `*Lazy` APIs yielding a lazy -> sequence (incompatible with async) as well as **Schema** DDL API's which are typically not used at runtime. - -For a quick preview of many of the new Async API's in action, checkout -[ApiSqlServerTestsAsync.cs](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLiteV45.Tests/ApiSqlServerTestsAsync.cs). - -### Async RDBMS Providers - -Currently only a limited number of RDBMS providers offer async API's which are only available in their **.NET 4.5** builds, which at this time are only: - - - [SQL Server .NET 4.5+](https://www.nuget.org/packages/ServiceStack.OrmLite.SqlServer) - - [MySQL .NET 4.5+](https://www.nuget.org/packages/ServiceStack.OrmLite.MySql) - -We've also added a -[.NET 4.5 build for Sqlite](https://www.nuget.org/packages/ServiceStack.OrmLite.Sqlite.Mono) -as it's a common use-case to swapout to use Sqlite's in-memory provider for faster tests. -But as Sqlite doesn't provide async API's under-the-hood we fallback to *pseudo async* support where we just wrap its synchronous responses in `Task` results. - -Regardless of whether the RDBMS provider offers Async API's, you still can use the same OrmLite async API's with all providers, -where the same Async OrmLite API's can also be used in DB Providers that doesn't natively support Async (i.e. Sqlite): - - - [ApiSqlServerTestsAsync.cs](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLiteV45.Tests/ApiSqlServerTestsAsync.cs) - - [ApiMySqlTestsAsync.cs](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLiteV45.Tests/ApiMySqlTestsAsync.cs) - - [ApiSqliteTestsAsync.cs](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLiteV45.Tests/ApiSqliteTestsAsync.cs) - -Only when these Async API's are run on an RDBMS provider with native async support (i.e. .NET 4.5 SqlServer or MySql) will you benefit from true -non-blocking Async I/O, otherwise it fallsback to *pseudo async* support, i.e. synchronous I/O datasets wrapped in `Task` Results. - -### Multiple Self References - -OrmLite's [POCO Reference conventions](https://github.com/ServiceStack/ServiceStack.OrmLite#reference-conventions) -has been expanded to include support for multiple Self References. - -The example below shows a customer with multiple `CustomerAddress` references which are able to be matched with -the `{PropertyReference}Id` naming convention, e.g: - -```csharp -public class Customer -{ - [AutoIncrement] - public int Id { get; set; } - public string Name { get; set; } - - [References(typeof(CustomerAddress))] - public int? HomeAddressId { get; set; } - - [References(typeof(CustomerAddress))] - public int? WorkAddressId { get; set; } - - [Reference] - public CustomerAddress HomeAddress { get; set; } - - [Reference] - public CustomerAddress WorkAddress { get; set; } -} -``` - -Once defined, it can be saved and loaded via OrmLite's normal Reference and Select API's, e.g: - -```csharp -var customer = new Customer -{ - Name = "Z Customer", - HomeAddress = new CustomerAddress { - Address = "1 Home Street", - Country = "US" - }, - WorkAddress = new CustomerAddress { - Address = "2 Work Road", - Country = "UK" - }, -}; - -db.Save(customer, references:true); - -var c = db.LoadSelect(q => q.Name == "Z Customer"); -c.WorkAddress.Address.Print(); // 2 Work Road - -var ukAddress = db.Single(q => q.Country == "UK"); -ukAddress.Address.Print(); // 2 Work Road -``` - -## [ServiceStack.Redis SSL Support](https://github.com/ServiceStack/ServiceStack/wiki/Secure-SSL-Redis-connections-to-Azure-Redis) - -The [most requested feature for ServiceStack.Redis](http://servicestack.uservoice.com/forums/176786-feature-requests/suggestions/6093693-support-ssl-connection-to-redis-instances-hosted-a) -has also been realized in this release with **ServiceStack.Redis** now supporting **SSL connections** making it suitable for accessing -remote Redis server instances over a **secure SSL connection**. - -![Azure Redis Cache](https://github.com/ServiceStack/Assets/raw/master/img/wikis/redis/azure-redis-instance.png) - -### Redis Use Cases - -Redis is normally used as a back-end datastore whose access is typically limited to Internal networks or authorized networks protected via firewalls. -The new SSL Support in the Redis Client also enables secure access to a redis-server instance over the Internet and public networks as well, -a scenario that's been recently popularized by Cloud hosting environments like Azure Redis Cache. - -### [Connecting to Azure Redis](https://github.com/ServiceStack/ServiceStack/wiki/Secure-SSL-Redis-connections-to-Azure-Redis) - -As connecting to [Azure Redis Cache](http://azure.microsoft.com/en-us/services/cache/) via SSL was the primary use-case for this feature, -we've added a new -[Getting connected to Azure Redis via SSL](https://github.com/ServiceStack/ServiceStack/wiki/Secure-SSL-Redis-connections-to-Azure-Redis) -to help you get started. - -### Redis Connection Strings - -Redis Connection strings have been expanded to support the more versatile URI format which is now able to capture most of Redis Client settings in a -single connection string (akin to DB Connection strings). - -Redis Connection Strings supports multiple URI-like formats, from a simple **hostname** or **IP Address and port** pair to a fully-qualified **URL** -with multiple options specified on the QueryString. - -Some examples of supported formats: - - localhost - 127.0.0.1:6379 - redis://localhost:6379 - password@localhost:6379 - clientid:password@localhost:6379 - redis://clientid:password@localhost:6380?ssl=true&db=1 - -> More examples can be seen in -[ConfigTests.cs](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/ConfigTests.cs) - -Any additional configuration can be specified as QueryString parameters. The full list of options that can be specified include: - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      SslboolIf this is an SSL connection
      DbintThe Redis DB this connection should be set to
      ClientstringA text alias to specify for this connection for analytic purposes
      PasswordstringUrlEncoded version of the Password for this connection
      ConnectTimeoutintTimeout in ms for making a TCP Socket connection
      SendTimeoutintTimeout in ms for making a synchronous TCP Socket Send
      ReceiveTimeoutintTimeout in ms for waiting for a synchronous TCP Socket Receive
      IdleTimeOutSecsintTimeout in Seconds for an Idle connection to be considered active
      NamespacePrefixstringUse a custom prefix for ServiceStack.Redis internal index colletions
      - -### New `RedisManagerPool` Client Manager - -With the introduction of Redis URI Connection Strings we've been able to simplify and streamline the existing `PooledRedisClientManager` -implementation that's been extracted out into clients manager called `RedisManagerPool`. -In addition to removing all above options on the Client Manager itself, we've also removed readonly connection strings so the configuration is -much simpler and more aligned with the common use-case. - -In most cases, `PooledRedisClientManager` is substitutable with `RedisManagerPool` e.g: - -```csharp -container.Register(c => - new RedisManagerPool(redisConnectionString)); -``` - -### New Generic API's for calling Custom Redis commands - -Most of the time when waiting to use a new [Redis Command](http://redis.io/commands) you'll need to wait for an updated version of -**ServiceStack.Redis** to add support for the new commands likewise there are times when the Redis Client doesn't offer every permutation -that redis-server supports. - -With the new `Custom` and `RawCommand` API's on `IRedisClient` and `IRedisNativeClient` you can now use the RedisClient to send your own -custom commands that can call adhoc Redis commands: - -```csharp -public interface IRedisClient -{ - ... - RedisText Custom(params object[] cmdWithArgs); -} - -public interface IRedisNativeClient -{ - ... - RedisData RawCommand(params object[] cmdWithArgs); - RedisData RawCommand(params byte[][] cmdWithBinaryArgs); -} -``` - -These API's return Custom Results in the generic data structures below: - -```csharp -public class RedisText -{ - public string Text { get; set; } - public List Children { get; set; } -} - -public class RedisData -{ - public byte[] Data { get; set; } - public List Children { get; set; } -} -``` - -These Custom API's take a flexible `object[]` arguments which accepts any serializable value e.g. -`byte[]`, `string`, `int` as well as any user-defined Complex Types which are transparently serialized -as JSON and send across the wire as UTF-8 bytes. - -```csharp -var ret = Redis.Custom("SET", "foo", 1); // ret.Text = "OK" - -byte[] cmdSet = Commands.Set; -ret = Redis.Custom(cmdSet, "bar", "b"); // ret.Text = "OK" - -ret = Redis.Custom("GET", "foo"); // ret.Text = "1" -``` - -There are also -[convenient extension methods](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/src/ServiceStack.Redis/RedisDataExtensions.cs) -on `RedisData` and `RedisText` that make it easy to access structured data, e.g: - -```csharp -var ret = Redis.Custom(Commands.Keys, "*"); -var keys = ret.GetResults(); // keys = ["foo", "bar"] - -ret = Redis.Custom(Commands.MGet, "foo", "bar"); -var values = ret.GetResults(); // values = ["1", "b"] - -Enum.GetNames(typeof(DayOfWeek)).ToList() - .ForEach(x => Redis.Custom(Commands.RPush, "DaysOfWeek", x)); -ret = Redis.Custom(Commands.LRange, "DaysOfWeek", 1, -2); -var weekDays = ret.GetResults(); - -weekDays.PrintDump(); // ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"] -``` - -and some more examples using Complex Types with the Custom API's: - -```csharp -var ret = Redis.Custom(Commands.Set, "foo", new Poco { Name = "Bar" }); // ret.Text = "OK" - -ret = Redis.Custom(Commands.Get, "foo"); // ret.Text = {"Name":"Bar"} -Poco dto = ret.GetResult(); - -dto.Name.Print(); // Bar -``` - -### New Config, Role and Client commands - -A number of New API's added in this can be seen below: - -```csharp -public interface IRedisClient -{ - ... - RedisText GetServerRoleInfo(); - string GetConfig(string item); - void SetConfig(string item, string value); - void SaveConfig(); - void ResetInfoStats(); - - string GetClient(); - void SetClient(string name); - void KillClient(string address); - long KillClients(string fromAddress = null, - string withId = null, RedisClientType? ofType = null, bool? skipMe = null); - List> GetClientsInfo(); - void PauseAllClients(TimeSpan duration); -} - -public interface IRedisNativeClient -{ - ... - void ConfigRewrite(); - RedisText Role(); - string ClientGetName(); - void ClientSetName(string client); - void ClientKill(string host); - long ClientKill(string addr = null, string id = null, string type = null, string skipMe = null); - byte[] ClientList(); - void ClientPause(int timeOutMs); -} -``` - -## [New VB.NET Add ServiceStack Reference!](https://github.com/ServiceStack/ServiceStack/wiki/VB.Net-Add-ServiceStack-Reference) - -This release also adds [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) -support for the last remaining major .NET language with the new first-class support for -[VB.NET Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/VB.Net-Add-ServiceStack-Reference)! - -This now allows any C#, F# or VB.NET client project to be able generate and end-to-end typed API for your services just by providing the -url of your remote ServiceStack instance, directly from within VS.NET! - -![Add ServiceStack Reference](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/add-service-ref-flow.png) - -After clicking OK, the servers DTO's and **ServiceStack.Client** NuGet package are added to the project, providing an instant typed API: - -![Calling a ServiceStack Service from VB.NET](https://github.com/ServiceStack/Assets/raw/master/img/apps/StackApis/call-service-vb.png) - -Thanks to the close semantics between the C# and VB.NET languages, we're able to add support for all C# -[customization options in VB.NET](https://github.com/ServiceStack/ServiceStack/wiki/VB.Net-Add-ServiceStack-Reference#dto-customization-options) as well. - -Much of the new VB.NET NativeTypes provider is thanks to the efforts of [@KevinHoward](https://github.com/KevinHoward). - -### [Upgrade ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) - -To take advantage of VB.NET Add ServiceStack Reference feature, -[Upgrade or Install ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) VS.NET Extension. -If you already have **ServiceStackVS** installed, uninstall it first from `Tools -> Extensions and Updates... -> ServiceStackVS -> Uninstall`. - -## Simplified UX for all languages - -Our first iteration of **Add ServiceStack Reference** for C# used a **T4 Template** to make it easy for clients to view and modify all -Customization options available and to be able to auto-generate the Server DTO's by modifying and saving (or re-running) the T4 template. - -As F# projects didn't support T4 Templates, when we added support for -[F# Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/FSharp-Add-ServiceStack-Reference) -we had to skip the T4 template and add the server-generated DTO's source file directly to the project. - -By skipping the T4 Template we pleasantly discovered we ended up with a nicer, simplified and more user-friendly UX, with less moving parts for -the default use case of generating client DTO's based on the -[Default Server Configuration](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference#change-default-server-configuration). - -### Improving Single Generated Source File Story - -We've since decided to embrace and provide a better development experience around a single source file approach and use it consistently in all -C#, F# and VB.NET projects - now resulting simpler **Add ServiceStack Reference** UX for all client projects. - -### Update ServiceStack Reference Context Menu Item - -With the latest **ServiceStackVS** you can now update the Server DTO's in all projects by clicking on `Update ServiceStack Reference` -on the context-menu, e.g: - -![Update ServiceStack Reference](https://github.com/ServiceStack/Assets/raw/master/img/servicestackvs/servicestack%20reference/updateref-vbnet.gif) - -### Updating and Customizing Generated Types - -To [customize the generated DTO's](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference#dto-customization-options) -on the client you can just uncomment the option you want to change directly in the **header comments** and hit save. -**ServiceStackVS** automatically watches for any changes to the generated dto source files (i.e. ending with `.dtos.cs`) and will automatically -send the uncommented options to the remote server referenced by the `BaseUrl` and replace the existing file with the updated DTOs instantly! - -Taking the example below, once we uncomment the `MakePartial` option and save the file, **ServiceStackVS** automatically sends a new request -to the remote ServiceStack instance, passing in the `?MakePartial=False` option when requesting updated DTO's: - -```csharp -/* Options: -Date: 2014-10-21 00:44:24 -Version: 1 -BaseUrl: http://stackapis.servicestack.net - -MakePartial: False -//MakeVirtual: True -//MakeDataContractsExtensible: False -//AddReturnMarker: True -//AddDescriptionAsComments: True -//AddDataContractAttributes: False -//AddIndexesToDataMembers: False -//AddResponseStatus: False -//AddImplicitVersion: -//InitializeCollections: True -//AddDefaultXmlNamespace: http://schemas.servicestack.net/types -*/ -``` - -After saving you'll be able to notice the DTO's are updated instantly with the `Date: *` changing to reflect the current time and the new -generated DTO's no longer containing `partial` classes. - -### ServiceStack.Text - -New `JsConfig.OnDeserializing` and dynamic `ShouldSerialize(string field)` customization options were added to ServiceStack's JSON and JSV -Text serializers by [@pavelsavara](https://twitter.com/pavelsavara). An example of these new customization options in action is visible below: - -```csharp -[DataContract] -public class CustomSerializedPoco -{ - [IgnoreDataMember] - public HashSet hasAttribute; - - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public int A { get; set; } - - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public int? B { get; set; } - - public bool? ShouldSerialize(string fieldName) - { - return hasAttribute == null - ? null - : hasAttribute.Contains(fieldName); - } - - public object OnDeserializing(string fieldName, object value) - { - if (hasAttribute == null) - hasAttribute = new HashSet(); - hasAttribute.Add(fieldName); - return value; - } -} -``` - -This change makes it possible to create dynamic POCO's that behave in a similar way that dynamic languages can, -e.g. After deserialization you can detect which fields were deserialized by inspecting the `hasAttribute` collection. - -The `ShouldSerialize` API, closely follows the existing `ShouldSerialize{X}` convention but instead allows for a single API -to handle all serializable properties. - -The API returns a `bool?` which has the following meaning: - - `true` - Should be emitted - - `false` - Should not be emitted - - `null` - Use default behavior - -This allows us to implement a custom type that can support full round-trip when the field on the original JSON payload allowing use to -implement a custom type with similar functionality to `IExtensibleDataObject` which allows survival and forwarding of unknown properties, but for JSON. - -## [RabbitMQ](https://github.com/ServiceStack/ServiceStack/wiki/Rabbit-MQ) - -RabbitMQ Server and Client now have optional `PublishMessageFilter` and `GetMessageFilter` callbacks which can be used to intercept -outgoing and incoming messages, the `IBasicProperties.Type` is also pre-populated with the Type name of the message body that was published, e.g: - -```csharp -var mqServer = new RabbitMqServer("localhost") -{ - PublishMessageFilter = (queueName, properties, msg) => { - properties.AppId = "app:{0}".Fmt(queueName); - }, - GetMessageFilter = (queueName, basicMsg) => { - var props = basicMsg.BasicProperties; - receivedMsgType = props.Type; //automatically added by RabbitMqProducer - receivedMsgApp = props.AppId; - } -}; - -using (var mqClient = mqServer.CreateMessageQueueClient()) -{ - mqClient.Publish(new Hello { Name = "Bugs Bunny" }); -} - -receivedMsgApp.Print(); // app:mq:Hello.In -receivedMsgType.Print(); // Hello -``` - -## Other Minor Changes - - - ServerEvents Server now echoes heartbeat messages back through to the listening connection, - `ServerEventsClient` only fires the `OnHeartbeat` callback when it's receives the echoed `cmd.Heartbeat` command message - - Request binding for `Path` and `QueryString` variables are added to DTO's with Request DTO's providing their own [custom body deserialization](https://github.com/ServiceStack/ServiceStack/wiki/Serialization-deserialization) by implementing `IRequiresRequestStream` - - New `IAppHost.OnDisposeCallbacks` available allowing **Plugins** to register callbacks when `AppHost` is disposed - - `Config.UseHttpsLinks` now modifies generated BaseUrl of all links to use `https` - - The `ResponseStatus` on Custom DTO's are now preserved when thrown inside a custom `HttpError` response - - Equality members added to `[Route]`, `[Authenticate]`, `[RequiredRole]` and `[RequiredPermission]` attributes - - `ToOptimizedResultUsingCache` no longer double-encodes raw `string` responses - - `MvcHtmlString` was moved to `ServiceStack.Html` namespace - - New `StaticFileHandler.ResponseFilter` added to be able to modify custom headers returned on static files - - Many of OrmLite's static Extension method classes were renamed into a more logical grouping. - These changes are source compatible for typical usage of OrmLite API's, i.e. referenced as extension methods - -## Breaking changes - -### Added new .NET 4.5 Builds - -In preparation for introducing Async API's we've added new **.NET 4.5 builds** for the following packages: - - - ServiceStack.OrmLite - - ServiceStack.OrmLite.Sqlite.Mono - - ServiceStack.OrmLite.SqlServer - - ServiceStack.OrmLite.MySql - - ServiceStack.Server - -When adding ServiceStack NuGet Packages to a **.NET 4.5** project you will now get these newer .NET 4.5 builds instead. -The additional builds means you could potentially run into issues if mixing .NET v4.0 and v4.5 builds as all dependencies -need to reference the same build version. - -Should you need to, the easiest way to fix any versioning issues is to make sure all projects use the same .NET Framework version -(e.g. .NET 4.5) and then just uninstall and re-install the ServiceStack NuGet packages. - -### Removed ThreadStatic OrmLite Configuration - -We've also removed our existing ThreadStatic config variables (used to temporarily override global configuration). -Most per-connection state is now stored on the connection e.g. `CommandTimeout` was previously overridden with: - -```csharp -var hold = OrmLiteConfig.TSCommandTimeout; -try { - OrmLiteConfig.TSCommandTimeout = 60; - db.Select(...); -} finally { - OrmLiteConfig.TSCommandTimeout = hold; -} -``` - -Is now set directly on the connection (and only applies to that connection), e.g: - -```csharp -using (var db = DbFactory.Open()) -{ - db.SetCommandTimeout(60); - db.Select(...); -} -``` - -Likewise if you ever need to access the current `OrmLiteConfig.DialectProvider`, it should now be retrieved from the `IDbConnection`, i.e: - -```csharp -db.GetDialectProvider(); -``` - -and if you ever need to access the underlying ADO.NET `IDbConnection` or `IDbCommand` you can access them via the following APIs: - -```csharp -IDbConnection adoDb = db.ToDbConnection(); -IDbCommand adoDbCmd = dmCmd.ToDbCommand(); -``` - -### IReturnVoid now returns void - -All `IReturnVoid` API's on Service Clients have been changed to return `void` instead of -`HttpWebResponse` which needed to be explicitly disposed by the callee. - -To access the `HttpWebResponse`, Request DTO's can be changed to `IReturn` - -```csharp -public class EmptyResponse : IReturn { ... } -``` - -Alternatively the Response can be specified on the call-site with: - -```csharp -HttpWebResponse response = client.Get(new EmptyResponse()); -``` - -# v4.0.32 Release Notes - -## FSharp Add ServiceStack Reference! - -We're happy to announce that the next language supported by [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) is F#! - -For a quick overview, [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) is a simple solution to WCF's Add Service Reference that provides a flexible alternative to sharing your compiled server DTO's assembly with clients. Now F# clients can easily add a reference to a remote ServiceStack instance and update typed DTO's directly from within VS.NET - reducing the burden and effort required to consume ServiceStack Services. - -### Example Usage - -The easiest way to Add a ServiceStack reference to your project is to right-click on your project to bring up [ServiceStackVS's](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) **Add ServiceStack Reference** context-menu item. This opens a dialog where you can add the url of the ServiceStack instance you want to typed DTO's for, as well as the name of the T4 template that's added to your project. - -[![Add ServiceStack Reference](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/add-service-ref-flow.png)](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/add-service-ref-flow.png) - -After clicking OK, the servers DTO's and [ServiceStack.Client](https://www.nuget.org/packages/ServiceStack.Client) NuGet package are added to the project, providing an instant typed API: - -[![Calling ServiceStack Service with FSharp](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/fsharp-add-servicestack-reference.png)](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/fsharp-add-servicestack-reference.png) - -### Updating a ServiceStack Reference - -Updating a ServiceStack reference works intuitively where you can right-click on the DTO's you want to update and click **Update ServiceStack Reference** on the context menu: - -[![Calling ServiceStack Service with FSharp](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/fsharp-update-servicestack-reference.png)](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/fsharp-update-servicestack-reference.png) - -### F# Client Example - -Just like with C#, F# Native Types can be used in ServiceStack's [Generic Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) providing and end-to-end Typed API whose PCL support also allows F# to be used in [mobile clients apps](https://github.com/ServiceStackApps/HelloMobile) as well. The basic [stackapis.servicestack.net](http://stackapis.servicestack.net/) Services example in F# looks like: - -```fsharp -let client = new JsonServiceClient("http://stackapis.servicestack.net") -let response = client.Get(new SearchQuestions( - Tags = new List([ "redis"; "ormlite" ]))) - -TypeSerializer.PrintDump(response) -``` - -## FSharp Native Types Notes - -Add ServiceStack Reference in FSharp projects works a little different to C# projects which [utilizes VS.NET's built-in T4 support](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference#add-servicestack-reference) to provide customization of DTO's on the client that auto-runs the T4 template implicitly on **Save** or explicitly with the **Run Custom Tool** context menu item. - -Since there's no support for T4 templates in F# Projects, clicking **Add ServiceStack Reference** skips the T4 template and just adds the generated F# Types using the server defaults. This ends up providing a simpler experience for F# clients in the default case. Customization of default behavior can still be done on the Server: - -### Change Default Server Configuration - -The above defaults are also overridable on the ServiceStack Server by modifying the default config on the `NativeTypesFeature` Plugin, e.g: - -```csharp -var typesConfig = this.GetPlugin().MetadataTypesConfig; -typesConfig.AddDataContractAttributes = false; -... -``` - -## F# Native Types Constraints - -As the ordering constraint in F# conflicted with the ordering of types by C# namespaces, the cleanest approach was to add all DTO's under a single namespace. By default the namespace used will be the base **ServiceModel** namespace which is overridable with the `GlobalNamespace` Config: - -```csharp -typesConfig.GlobalNamespace = "Client.Namespace"; -``` - -This does mean that each DTO type name needs to be unique which is a best-practice that's now a requirement in order to make use of F# native types. Another semantic difference is that any C# partial classes are converted into top-level classes in F#. - -For more documentation about F# Native Types including info on each of the config options supported checkout the [F# Add ServiceStack Reference wiki](https://github.com/ServiceStack/ServiceStack/wiki/FSharp-Add-ServiceStack-Reference). - -### [Upgrade ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) - -To take advantage of this F# Add ServiceStack Reference [Upgrade or Install ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) VS.NET Extension. If you already have **ServiceStackVS** installed, uninstall it first from `Tools -> Extensions and Updates... -> ServiceStackVS -> Uninstall`. - -### Nested classes and Enums - -Support for Enums and Nested classes are now supported on both C# and F# Native Types. - -## Improved integration with MVC and ASP.NET - -We've improved integration for making use of ServiceStack components in existing ASP.NET MVC and WebForms Web Applications. The internals of `ServiceStackController` have been rewritten to share a common code-base with the new WebForms `ServiceStackPage` WebForms base page, both provide easy access to the same clean, high-performance components found in ServiceStack's `Service` base class, directly from within your MVC Controllers and WebForm pages. - -This is an outline of the API's found in MVC's `ServiceStackController` and WebForms `ServiceStackPage`: - -```csharp -public class ServiceStackController : Controller -{ - //... - IServiceStackProvider ServiceStackProvider { get; set; } - IAppSettings AppSettings { get; set; } - IHttpRequest ServiceStackRequest { get; set; } - IHttpResponse ServiceStackResponse { get; set; } - ICacheClient Cache { get; set; } - IDbConnection Db { get; set; } - IRedisClient Redis { get; set; } - IMessageFactory MessageFactory { get; set; } - IMessageProducer MessageProducer { get; set; } - ISessionFactory SessionFactory { get; set; } - ISession SessionBag { get; set; } - bool IsAuthenticated { get; set; } - - T TryResolve(); - T ResolveService(); - object Execute(object requestDto); - object ForwardRequestToServiceStack(IRequest request=null); - IAuthSession GetSession(bool reload = true); - TUserSession SessionAs(); - void ClearSession(); - void PublishMessage(T message); -} -``` - -### Use ServiceStack Authentication - -One benefit of integration with ServiceStack is to be able to make use of ServiceStack's simple and flexible [Authentication Providers](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization) which require minimal configuration and supports a number of different [Session Providers](https://github.com/ServiceStack/ServiceStack/wiki/Caching) and persistent [Data Store back-ends](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization#userauth-persistence---the-iuserauthrepository) to make it easy to integrate with an existing environment. - -### New MVC and WebForms Examples - -To illustrate the seamless integration with ServiceStack, we've created 2 new authentication-enabled example websites: - - - **ASP.NET MVC** Live Demo: [mvc.servicestack.net](http://mvc.servicestack.net/) and [source code](https://github.com/ServiceStack/Test/tree/master/src/Mvc) - - **ASP.NET WebForms** Live Demo: [webforms.servicestack.net](http://webforms.servicestack.net/) and [source code](https://github.com/ServiceStack/Test/tree/master/src/WebForms) - -![MVC with ServiceStack Authentication](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/mvc-integration.png) - -### Integrating with ServiceStack from MVC or WebForms - -We'll go through the MVC example to showcase the different ways you can integrate with ServiceStack from an external Web Framework. - -#### Using ResolveService to call Services directly - -The `Login` Action is a standard MVC Action handling HTML Form input accepting 3 parameters, a `userName`, `password` as well as a relative `redirect` url to redirect to when authentication is successful. Login uses the `ResolveService` API which just resolves an auto-wired instance of the ServiceStack `AuthenticateService` from the IOC and injects the current HTTP Request context, which we then use to call a method on the Service directly: - -```csharp -public ActionResult Login(string userName, string password, string redirect=null) -{ - if (ModelState.IsValid) - { - try - { - using (var authService = ResolveService()) - { - var response = authService.Authenticate(new Authenticate { - provider = CredentialsAuthProvider.Name, - UserName = userName, - Password = password, - RememberMe = true, - }); - - // add ASP.NET auth cookie - FormsAuthentication.SetAuthCookie(userName, true); - - return Redirect(string.IsNullOrEmpty(redirect) ? "/" : redirect); - } - } - catch (Exception ex) - { - ModelState.AddModelError(string.Empty, ex.Message); - } - } - - return View("Index", GetViewModel()); -} -``` - -> Since the above example calls the Service method directly any exceptions raised by the Service implementation are thrown and caught as normal. - -#### Using Execute to process Request DTO's - -The `Logout()` MVC Action uses ServiceStack's `Execute()` API which can call the desired ServiceStack Service with just a populated Request DTO: - -```csharp -public ActionResult Logout() -{ - Execute(new Authenticate { provider = "logout" }); - FormsAuthentication.SignOut(); - - return Redirect("/"); -} -``` - -#### Using ForwardRequestToServiceStack to proxy HTTP Requests - -The `ForwardingController` handles OAuth callbacks that have been configured to callback to `/auth/*` route which is handled by MVC as ServiceStack is mounted at and only configured to handle `/api` requests. - -Instead of creating new OAuth Applications with each provider to use the new `/api/auth/*` callback url so ServiceStack can handle the OAuth callback, we can use just use the new `ForwardRequestToServiceStack()` which just forwards the incoming HTTP Request from MVC to ServiceStack to process, effectively acting as a proxy: - -```csharp -routes.MapRoute("Forwarding", "auth/{*pathinfo}", - new { controller = "Forwarding", action = "Index" }); -... - -public class ForwardingController : ServiceStackController -{ - public ActionResult Index() - { - var response = ForwardRequestToServiceStack(); - if (ServiceStackResponse.IsClosed) return new EmptyResult(); - - string redirectUrl; - var httpResult = response as IHttpResult; - if (httpResult != null && httpResult.Headers.TryGetValue(HttpHeaders.Location, out redirectUrl)) - return Redirect(redirectUrl); - - return Redirect("/"); - } -} -``` - -The `Execute()` and `ForwardRequestToServiceStack()` are high-level API's that call into ServiceStack's internal Request pipeline, executing any Action Filters and also converts any exceptions into a populated serializable Response DTO with a populated `ResponseStatus` as would be returned to Service Clients. - -### Authentication Attributes - -Since we're using ServiceStack for Authentication, we're also able to re-use ServiceStack's Authentication Attribute Filters directly on MVC Controllers and WebForm Pages just as if they were ServiceStack Services, e.g: - -```csharp -[Authenticate] -public class AuthOnlyController : ServiceStackController -{ - public ActionResult Index() - { - return View(SessionAs()); - } -} -``` - -The above controller hanldes the [mvc.servicestack.net/AuthOnly](http://mvc.servicestack.net/AuthOnly) route which only allows access to Authorized users. If a user is not authenticated they're automatically redirected to [/?redirect=/AuthOnly#f=Unauthorized](http://mvc.servicestack.net/?redirect=%2fAuthOnly#f=Unauthorized) to prompt the user to login, after successfully logging in it will redirect back to the original `/AuthOnly` url. - -### Required Role or Permission - -The `[RequiredRole]` and `[RequiredPermission]` attributes work similar to the `[Authentication]` attribute except they also assert that the user is a member of the specified role: - -```csharp -[RequiredRole("TheRole")] -public class RequiresRoleController : ServiceStackController -{ - public ActionResult Index() - { - return View(SessionAs()); - } -} -``` - -The above Controller handles the [/RequiresRole](http://mvc.servicestack.net/RequiresRole) Route and will only grant access if the Authenticated User is also a member of the **TheRole**. - -### Calling ServiceStack Services Directly - -The simplest way to consume ServiceStack Services requiring the least effort and moving parts is to call them directly: - -#### Using ServiceStack OAuth in MVC - -Integrating with ServiceStack's OAuth providers requires the least effort as they're linkable directly in the format `/api/auth/{provider}` which is handled by ServiceStack's OAuth Service who initiates the Authentication process by redirecting to the selected OAuth provider: - -![MVC OAuth with HTML](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/mvc-auth.png) - -#### Calling ServiceStack with Ajax in MVC - -Posting HTML Forms directly to ServiceStack Services isn't that much more effort, Start with a plain HTML Form with field names that match with the Services property names: - -![MVC Register with HTML](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/mvc-register.png) - -We can then use ServiceStack's built-in [ss-utils.js JavaScript Libraray](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library) to take care of Ajaxifying, auto-binding and submitting the form via Ajax. It also has built-in support for [Bootstrap Forms Field Validation conventions](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library#bootstrap-forms) to automatically bind errors to the appropriate fields. The only custom code required is to bind the form is then: - -```javascript -$("#form-register").bindForm({ - success: function (r) { location.href = '/'; } -}); -``` - -In this case we've added a success callback to redirect to the home page if the registration was successful which will either be authenticated with the newly registered user if **Auto Login** was checked, otherwise you can use the login form to Sign in as the newly registered user. - -## [Server Events](https://github.com/ServiceStack/ServiceStack/wiki/Server-Events) - -There are new custom hooks on `ServerEventsFeature` to allow for further customization and deeper introspection of ServiceStack's Server Events: - - - `OnInit` - Invoked when clients first connect to the `event-stream`, can be used to add additional HTTP Headers back to the client - - `OnPublish` - Fired after each message is published with the active Response and the raw message that was published - -### Add Authentication support to .NET ServerEvents Client - -There are new explicit `Authenticate` and `AuthenticateAsync` API's which can be used to authenticate the ServerEvents ServiceClient which now **shares cookies** with the WebRequest that connects to the `/event-stream` so authenticating with the Server Events ServiceClient will also authenticate the `/event-stream` HTTP Connection: - -```csharp -client.Authenticate(new Authenticate { - provider = CredentialsAuthProvider.Name, - UserName = "user", - Password = "pass", - RememberMe = true, -}); - -client.Start(); -``` - -Which is also equivalent to: - -```csharp -client.ServiceClient.Post(new Authenticate { - provider = CredentialsAuthProvider.Name, - UserName = "user", - Password = "pass", - RememberMe = true, -}); -``` - -### Limiting Server Events to Authenticated Clients Only - -There's a new `LimitToAuthenticatedUsers` option in `ServerEventsFeature` to limit access to authenticated clients only: - -```csharp -Plugins.Add(new ServerEventsFeature { - LimitToAuthenticatedUsers = true, -}); -``` - -When enabled it will return a `401 Unauthorized` for non-authenticated clients. - -### JavaScript ServerEvents Client - -The [Server Events JavaScript Client](https://github.com/ServiceStack/ServiceStack/wiki/JavaScript-Server-Events-Client) now auto-reconnects when a heartbeat request fails by calling the new `$.ss.reconnectServerEvents()` API. - -## Funq IOC - -Funq now supports Lazy dependencies where you can `Func` factories to delay the resolution of dependencies to only when the Service is needed. The factories also support Multiple lazy arguments (up to 3 args): - -```csharp -container.RegisterAutoWiredAs(); -container.RegisterAutoWiredAs(); -container.RegisterAutoWiredAs(); - -container.RegisterAutoWired(); - -public class Dependency -{ - Func ctorFoo; - public Dependency(Func ctorFoo) - { - this.ctorFoo = ctorFoo; - } - - public Func Foo { get; set; } - - public Func FooBar { get; set; } - - public Func FooBarBaz { get; set; } - - public object Execute() - { - int total = 0; - var foo = ctorFoo(); - var bar = FooBar(foo); - var baz = FooBarBaz(foo, bar); - return bax.Execute(); - } -} -``` - -An alternative approach to resolving lazy dependency is to use a Lazy Property which is our preferred approach since allows the call-site to be transparent and retain a clean API, e.g: - -```csharp -public virtual IDbConnectionFactory DbFactory { get; set; } - -IDbConnection db; -public virtual IDbConnection Db -{ - get { return db ?? (db = DbFactory.OpenDbConnection()); } -} -``` - -This technique is used in the built-in [Repository Base](https://github.com/ServiceStack/ServiceStack/blob/8dcbbdb7dbe20fd3201cde100370564e8577a019/src/ServiceStack/ILogic.cs#L38) and [Logic Base](https://github.com/ServiceStack/ServiceStack/blob/8dcbbdb7dbe20fd3201cde100370564e8577a019/src/ServiceStack/ILogic.cs#L55) base classes which your dependencies can inherit from to enable lazy access to common ServiceStack providers. - -## App Settings - -### New Providers - -There's a new `EnvironmentVariableSettings` AppSettings provider to source configuration from Environment variables as well as a new `MultiAppSettings` AppSettings provider that enables reading configuration from multiple configuration sources. - -With these new providers we can setup a cascading configuration that first checks Environment variables, then looks in a local `~/appsettings.txt` plain-text file before falling back to `Web.config`: - -```csharp -AppSettings = new MultiAppSettings( - new EnvironmentVariableSettings(), - new TextFileSettings("~/appsettings.txt".MapHostAbsolutePath()), - new AppSettings()); -``` - -### New Apis - -New `GetAllKeys()` and `Exists()` were added to all `IAppSettings` providers: - -```csharp -public interface IAppSettings -{ - List GetAllKeys(); - bool Exists(string key); - //... -} -``` - -This makes it easy to scan and retrieve all related keys, e.g: - -```csharp -var devKeys = appSettings.GetAllKeys().Where(x => x.Matches("Dev.*")); -``` - -## [Session](https://github.com/ServiceStack/ServiceStack/wiki/Sessions) - -### Use HTTP Headers to Send Session Cookies - -You can now make a Session-enabled request with HTTP Headers instead of Cookies. The Session HTTP Headers have a `X-` prefix before the Session Id, i.e: `X-ss-id`, `X-ss-pid` and `X-ss-opts` - -### New API's for Session Bag - -New API's for storing and retrieving POCO's in a session bag without specifying a key (key defaults to Type Name): - -```csharp -SessionBag.Set(unAuthInfo); -var unAuthInfo = SessionBag.Get(); -``` - -New `GetSessionBag()` extension methods on `IRequest` and `IServiceBase` make it easier to access the users dynamic Session Bag from outside of a Service. E.g the example below shows how to copy any Anonymous User Session info into the Users typed Session when they Sign In: - -```csharp -public class CustomUserSession : AuthUserSession -{ - [DataMember] - public string UnAuthInfo { get; set; } - - public override void OnAuthenticated(IServiceBase authService, IAuthSession session, - IAuthTokens tokens, Dictionary authInfo) - { - UnAuthInfo = authService.GetSessionBag().Get(); - } -} -``` - -## OrmLite - -### New OrderBy API's for Joined Tables - -You can now Order By fields from Joined Tables in an SqlExpression: - -```csharp -var q = db.From() - .Join() - .OrderBy(x => x.Name); -``` - -### Count Queries - - - New `RowCount()` API added to return the number of rows in a query - - Aggregate `Count()` queries that return more than a single row are summed together - -### SelectInto Mapping - - - You no longer need to repeat `[Alias]` attributes when projecting results into different types with `db.SelectInto` API's as fields are now mapped by POCO Property names - -## ServiceStack.Text - - - Default delimiter of `ParseKeyValueText` changed from `:` to ` ` (space) - - New `string.Matches()` extension method to perform Glob-style matches - - `GetGenericType()` extension has been renamed to the more appropriate `FirstGenericType()` - - The `__type` info for late-bound types is no longer affected by white-space - -## Other - - - Metadata detail pages now include any types referenced in the Request and Response DTOs - - Rabbit MQ Clients no longer auto-declare Server Named Queues `amq.*` - -## Community - -### New [ServiceStack Succinctly](http://www.agile-code.com/blog/servicestack-succinctly-free-e-book/) Free e-book! - -[ServiceStack Succinctly](http://www.agile-code.com/blog/servicestack-succinctly-free-e-book/) is a new free e-book by [Zoran Maksimovic](https://twitter.com/zoranmax) which runs through the basics of creating and implementing a simple order management system with ServiceStack: - -Free ServiceStack Succinctly e-book - -### Table of Contents - - 1. ServiceStack Overview - 2. ServiceStack Basics - 3. Order Management System - 4. Solution Configuration - 5. Service Implementation - 6. Pagination - 7. Authentication - 8. Caching - 9. Logging - 10. Profiling - 11. Extending ServiceStack - 12. Documenting Web Services - -# v4.0.31 Release Notes - -The most requested feature since our last release was to expand our last releases support for [Server Sent Events](https://github.com/ServiceStackApps/Chat#server-sent-events) with both a scale-out **Redis ServerEvents back-end** for use in load-balanced App Servers scenarios as well as a **typed C# ServerEvents Client** - we're happy to announce we've been able to deliver both features in this release! - -#### Major features in this release - - - Server Events - - [Redis ServerEvents](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#redis-serverevents) - - [C# ServerEvents Client](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#c-serverevents-client) - - Redis - - [Redis Pub/Sub Server](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#redis-pubsub-server) - - AppSettings - - [First-class AppSettings](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#first-class-appsettings) - - [Writable AppSettings API](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#appsettings-are-now-writable) - - [Metadata Pages](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#metadata-pages) - - Authentication - - [WebSudo](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#web-sudo) - - [Auth Events](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#auth-events) - - [OrmLite](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#ormlite) - - [Text](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#text) - - Community - - [ServiceStack MiniProfiler Toolkit](https://github.com/ServiceStack/ServiceStack/blob/master/release-notes.md#servicestack-miniprofiler-toolkit) - -## Redis ServerEvents - -One limitation the default `MemoryServerEvents` implementation has is being limited for use within a single App Server where all client connections are maintained. This is no longer a limitation with the new **Redis ServerEvents back-end** which utilizes a distributed redis-server back-end to provide a scale-out option capable of serving fan-out/load-balanced App Servers. If you're familiar with SignalR, this is akin to [SignalR's scaleout with Redis back-end](http://www.asp.net/signalr/overview/signalr-20/performance-and-scaling/scaleout-with-redis). - -`RedisServerEvents` is a drop-in replacement for the built-in `MemoryServerEvents` that's effectively a transparent implementation detail, invisible to Server or Client API's where both implementations even [share the same integration Tests](https://github.com/ServiceStack/ServiceStack/blob/b9eb34eb80ff64fa1171d2f7f29ef359c3580eed/tests/ServiceStack.WebHost.Endpoints.Tests/ServerEventTests.cs#L169-L189). - -![Redis ServerEvents Scale Out](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/gap/Chat/redis-scaleout.png) - -### Enabling RedisServer Events - -As a drop-in replacement it can easily be configured with just a few lines of code, as seen in the updated Chat App which can run on either [Memory or Redis ServerEvents providers](https://github.com/ServiceStackApps/Chat/blob/326617e88272d7cc0a8b7513272cf055378957e2/src/Chat/Global.asax.cs#L46-L54): - -```csharp -var redisHost = AppSettings.GetString("RedisHost"); -if (redisHost != null) -{ - container.Register(new PooledRedisClientManager(redisHost)); - - container.Register(c => - new RedisServerEvents(c.Resolve())); - - container.Resolve().Start(); -} -``` - -The above configuration will use Redis ServerEvents if there's a `RedisHost` **appSetting** in Chat's [Web.config](https://github.com/ServiceStackApps/Chat/blob/326617e88272d7cc0a8b7513272cf055378957e2/src/Chat/Web.config#L21): - -```xml - -``` - -### Cross-platform Memory and Redis ServerEvent Enabled Chat.exe - -To showcase Redis ServerEvents in action, we've prepared a stand-alone [ServiceStack.Gap](https://github.com/ServiceStack/ServiceStack.Gap) version of [Chat](http://chat.servicestack.net) compiled down into a single **Chat.exe** that can run on either Windows and OSX with Mono which can be downloaded from: - -### [Chat.zip](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/Chat.zip) (1.2MB) - -[![Redis ServerEvents Preview](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/redis-server-events.gif)](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/Chat.zip) - -> As Chat only runs on **2 back-end Services**, it fits well within [ServiceStack's Free Quota's](https://servicestack.net/download#free-quotas) which can be further customized and enhanced without a commercial license. - -Running **Chat.exe** without any arguments will run Chat using the default **Memory ServerEvents**. This can be changed to use **Redis ServerEvents** by [un-commenting this line in appsettings.txt](https://github.com/ServiceStack/ServiceStack.Gap/blob/master/src/Chat/Chat/appsettings.txt#L5): - -``` -#redis localhost -``` - -This will require a **redis-server** running on `localhost`. If you don't have redis yet, [download redis-server for Windows](https://github.com/ServiceStack/redis-windows). - -Alternatively you can specify which **port** to run Chat on and change it to use Redis ServerEvents by specifying the **redis** instance it should connect to on the command-line with: - -``` -Chat.exe /port=1337 /redis=localhost -``` - -Also included in `Chat.zip` are [test-fanout-redis-events.bat](https://github.com/ServiceStack/ServiceStack.Gap/blob/master/src/Chat/build/test-fanout-redis-events.bat) and equivalent [test-fanout-redis-events.sh](https://github.com/ServiceStack/ServiceStack.Gap/blob/master/src/Chat/build/test-fanout-redis-events.sh) helper scripts for **spawning multiple versions of Chat.exe** on different ports (and backgrounds) for **Windows or OSX**, showing how multiple clients are able to send messages to each other via Redis whilst being subscribed to different HTTP Servers: - -``` -START Chat.exe /port=1337 /redis=localhost -START Chat.exe /port=2337 /redis=localhost /background=http://bit.ly/1oQqhtm -START Chat.exe /port=3337 /redis=localhost /background=http://bit.ly/1yIJOBH -``` - -This script was used to create the animated gif above to launch **3 self-hosting instances of Chat.exe** running on **different ports**, all connected to each other via Redis. This enables some interesting peer-to-peer scenarios where users are able to run a network of (CPU/resource isolated) decentralized stand-alone HTTP Servers on their local machines, but can still communicate with each other via redis. - -## C# ServerEvents Client - -Like ServiceStack's other [C# Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client), the new `ServerEventsClient` is a [portable library](https://github.com/ServiceStackApps/HelloMobile) contained in the `ServiceStack.Client` NuGet package: - -``` -PM> Install-Package ServiceStack.Client -``` - -And like the Service Clients it requires the `BaseUri` of your ServiceStack instance as well as an optional `channel` for the client to subscribe to: - -```csharp -var client = new ServerEventsClient("http://chat.servicestack.net", channel:"home"); -``` - -### Managed Connection - -The **C# ServerEvent Client** is a managed .NET client with feature parity with the [ServiceStack's JavaScript client](https://github.com/ServiceStackApps/Chat#client-bindings---ss-utilsjs) that **auto-reconnects** when a connection is lost, **sends periodic heartbeats** to maintain an active subscription as well as **auto-unregistering** once the client stops listening for messages, or gets disposed. - -### Handling Server Events - -Unlike other C# clients, the ServerEvents Client is mainly reactive in that it's primarily waiting for Server Events to be initiated from a remote server instead of the typical scenario in which requests are initiated by clients. To maximize utility, there are a number of different API's to receive and process messages: - -### Assigning Callback Handlers - -One way to receive messages (useful in long-running clients) is to assign handlers for each of the different events that are fired. This example shows how to capture all the different events a Client can receive: - -```csharp -ServerEventConnect connectMsg = null; -var msgs = new List(); -var commands = new List(); -var errors = new List(); - -var client = new ServerEventsClient(baseUri) { - OnConnect = e => connectMsg = e, - OnCommand = commands.Add, - OnMessage = msgs.Add, - OnException = errors.Add, -}.Start(); -``` - -Once the Client is configured, calling `Start()` will start listening for messages and calling `Stop()` or `Dispose()` will cancel the background HTTP connection and stop it listening for server events. - -### Customizing Metadata sent to clients - -As ServerEvents have deep integration with the rest of ServiceStack we're able to offer [Typed Messages](https://github.com/ServiceStack/ServiceStack/blob/71b51d231d1ddb2ba7da39613e216ab75fd181c0/src/ServiceStack.Client/ServerEventsClient.cs#L14-L44) containing the users `UserAuthId`, `DisplayName` and `ProfileUrl` of the users avatar when it's available. The typed messages also offer an extensible `Dictionary Meta` collection for maintaining custom metadata that can be sent to clients by appending to them in the ServerEventsFeature hooks, which can be defined when registering `ServerEventsFeature`: - -```csharp -Plugins.Add(new ServerEventsFeature { - // private Connect args - OnConnect = (subscription,httpReq) => AppendTo(subscription.Meta), - - // public Join/Leave args - OnCreated = (subscription,httpReq) => AppendTo(subscription.Meta), -}) -``` - -### Using C# Async/Await friendly API's - -Depending on your use-case, if you only want to use the ServerEvent Client for a short-time to listen for predictable responses (i.e. waiting for a Server callback on a pending request) you can alternatively use the Task-based API's letting you to participate in C# async/await workflows: - -```csharp -var client = new ServerEventsClient(baseUri, channel="Home"); - -// Wait to receive onConnect event -ServerEventConnect connectMsg = await client.Connect(); - -// Wait to receive onJoin command event -ServerEventCommand joinMsg = await client.WaitForNextCommand(); - -// Hold a future task to get notified once a msg has been received -Task msgTask = client1.WaitForNextMessage(); - -// Send a Web Service Request using the built-in JsonServiceClient -client.ServiceClient.Post(new PostChatToChannel { - Channel = client.Channel, // The channel we're listening on - From = client.SubscriptionId, // SubscriptionId Populated after Connect() - Message = "Hello, World!", -}); - -// Wait till we receive the chat Msg event we sent earlier -ServerEventMessage msg = await msgTask; -``` - -The above example showcases the **3 Task-based API's** available: - - 1. `Connect()` wait till receiving confirmation of a successful event subscription - 2. `WaitForNextCommand()` wait for the next `onJoin` or `onLeave` subscription events - 3. `WaitForNextMessage()` wait for the next message published to the channel - -The `ServiceClient` property lets you access a `JsonServiceClient` that's pre-configured with the clients `BaseUri` so that is primed for Sending Web Service Requests with. - -After the ServerEvent Client has connected, the `ConnectionInfo` property is populated with the typed `ServerEventConnect` response. - -### Message Event Handlers - -The above examples show generic API's for receiving any type of message, but just like in the JavaScript client, more fine-grained API's are available for handling specific message types. - -The `Handlers` dictionary is akin to the JavaScript Client's [Global Event Handlers](https://github.com/ServiceStackApps/Chat#global-event-handlers) which specify lambda's to be executed when messages are sent with the `cmd.*` selector: - -```csharp -client.Handlers["chat"] = (client, msg) => { - var chatMsg = msg.Json.FromJson(); //Deserialize JSON string to typed DTO - "Received '{0}' from '{1}'".Print(chatMsg.Message, chatMsg.FromName); -}; -``` - -Roughly translates to the equivalent JavaScript below: - -```javascript -$(source).handleServerEvents({ - handlers: { - chat: function (msg, event) { - console.log("Received " + msg.message + " from " + msg.fromName); - } - } -}); -``` - -Where both methods handle the `ChatMessage` sent with the `cmd.chat` selector. - -### Named Receivers - -Whilst handlers provide a light way to handle loose-typed messages, there's a more structured and typed option that works similar to ServiceStack's `IService` classes but are used to instead handle typed Server Event Messages. - -To be able to handle messages with your own classes, get them to implement the `IReceiver` empty marker interface: - -```csharp -public interface IReceiver -{ - void NoSuchMethod(string selector, object message); -} -``` - -Whilst primarily a marker interface, `IReceiver` does include a `NoSuchMethod` API to be able to handle messages sent with a unknown selector **target** that doesn't match any defined method or property. - -**Named Receivers** are equivalent to [Receivers](https://github.com/ServiceStackApps/Chat#receivers) in the JavaScript client which can be assigned to handle all messages sent to a receiver with the selector format: - -``` -{receiver}.{target} -``` - -A Named Receiver can be registered with the API below: - -```csharp -client.RegisterNamedReceiver("test"); -``` - -Which will forward all messages with a `test.*` selector to an instance of the `TestNamedReceiver` Type - -```csharp -public class TestNamedReceiver : ServerEventReceiver -{ - public void FooMethod(CustomType request) {} // void return type - - public CustomType BarMethod(CustomType request) - { - return request; // works with any return type, which are ignored - } - - public CustomType BazSetter { get; set; } // Auto populate properties - - public override void NoSuchMethod(string selector, object message) - { - var msg = (ServerEventMessage)message; - var nonExistentMethodCustomType = msg.Json.FromJson(); - } -} -``` - -This is roughly equivalent to the following JavaScript code: - -```javascript -$(source).handleServerEvents({ - receivers: { - test: { - FooMethod: function (msg, event) { ... }, - BarMethod: function (msg, event) { ... }, - BazSetter: null, - } - } -}); -``` - -> The [ServerEventReceiver](https://github.com/ServiceStack/ServiceStack/blob/68c7159037e7cf2a519d482b7dae524ca073da20/src/ServiceStack.Client/ServerEventsClient.Receiver.cs#L16-L28) is a convenient base class that in addition to implementing `IReceiver` interface, gets injected with the `Client` as well as additional context about the raw message available in `base.Request`. - -#### Unknown Message Handling - -One difference in the JavaScript client is that messages with **unknown** targets are assigned as properties on the `test` receiver, e.g `test.QuxTarget = {..}`. - -### Sending messages to Named Receivers - -Once registered, an instance of `TestNamedReceiver` will process messages sent with a `test.*` selector. The example below shows how to send a DTO to each of `TestNamedReceiver` defined methods and properties: - -```csharp -public class MyEventServices : Service -{ - public IServerEvents ServerEvents { get; set; } - - public void Any(CustomType request) - { - ServerEvents.NotifyChannel("home", "test.FooMethod", request); - ServerEvents.NotifyChannel("home", "test.BarMethod", request); - ServerEvents.NotifyChannel("home", "test.BazSetter", request); - - ServerEvents.NotifyChannel("home", "test.QuxTarget", request); - } -} -``` - -### Life-cycle of Receivers - -Similar to **Services** in ServiceStack, each message is processed with an instance of the Receiver that's resolved from `ServerEventsClient.Resolver` which by default uses the [NewInstanceResolver](https://github.com/ServiceStack/ServiceStack/blob/ec0226b97227048c3bd7c24667a71e7af7e1ff31/src/ServiceStack.Client/ServerEventsClient.Receiver.cs#L30-L36) to execute messages using a new instance of the Receiver Type: - -```csharp -public class NewInstanceResolver : IResolver -{ - public T TryResolve() - { - return typeof(T).CreateInstance(); - } -} -``` - -This can be changed to re-use the same instance by assigning a [SingletonInstanceResolver](https://github.com/ServiceStack/ServiceStack/blob/ec0226b97227048c3bd7c24667a71e7af7e1ff31/src/ServiceStack.Client/ServerEventsClient.Receiver.cs#L38-L46) instead: - -```csharp -public class SingletonInstanceResolver : IResolver -{ - ConcurrentDictionary Cache = new ConcurrentDictionary(); - - public T TryResolve() - { - return (T)Cache.GetOrAdd(typeof(T), type => type.CreateInstance()); - } -} - -client.Resolver = new SingletonInstanceResolver(); -``` - -We can also have it resolve instances from your preferred IOC. Here's an example showing how to register all Receiver Types, auto-wire them with any custom dependencies, and instruct the client to resolve instances from our IOC: - -```csharp -// Register all Receivers: -client.RegisterNamedReceiver("test"); -... - -// Register all dependencies used in a new Funq.Container: -var container = new Container(); -container.RegisterAs(); - -// Go through an auto-wire all Registered Receiver Types with Funq: -container.RegisterAutoWiredTypes(client.ReceiverTypes); - -// Change the client to resolve receivers from the new Funq Container: -client.Resolver = container; -``` - -We can assign `Funq.Container` directly as it already implements the [IResolver](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Configuration/IResolver.cs) interface, whilst you can re-use the existing IOC **Container Adapters** to [enable support for other IOCs](https://github.com/ServiceStack/ServiceStack/wiki/The-IoC-container#use-another-ioc-container). - -### The Global Receiver - -Whilst Named Receivers are used to handle messages sent to a specific namespaced selector, the client also supports registering a **Global Receiver** for handling messages sent with the special `cmd.*` selector. - -#### Handling Messages with the Default Selector - -All `IServerEvents` Notify API's inlcudes [overloads for sending messages without a selector](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/ServerEventsFeature.cs#L743-L771) that by convention will take the format `cmd.{TypeName}`. - -These events can be handled with a Global Receiver **based on Message type**, e.g: - -```csharp -public class GlobalReceiver : ServerEventReceiver -{ - public SetterType AnyNamedProperty { get; set; } - - public void AnyNamedMethod(CustomType request) - { - ... - } -} - -client.RegisterReceiver(); -``` - -Which will be called when messages are sent without a selector, e.g: - -```csharp -public class MyServices : Service -{ - public IServerEvents ServerEvents { get; set; } - - public void Any(Request request) - { - ServerEvents.NotifyChannel("home", new CustomType { ... }); - ServerEvents.NotifyChannel("home", new SetterType { ... }); - } -} -``` - -As Global Receivers handle other messages sent with the `cmd.*` selector and can be re-used as a named receiver, we can define a single class to handle all the different custom messages sent in [chat.servicestack.net](http://chat.servicestack.net) App, E.g: - -``` -cmd.chat Hi -cmd.announce This is your captain speaking... -cmd.toggle#channels -css.background-image url(https://servicestack.net/img/bg.jpg) -... -``` - -The above messages can all be handled with the Receiver below: - -```csharp -public class JavaScriptReceiver : ServerEventReceiver -{ - public void Chat(ChatMessage message) { ... } - public void Announce(string message) { ... } - public void Toggle(string message) { ... } - public void BackgroundImage(string cssRule) { ... } -} - -client.RegisterNamedReceiver(); -client.RegisterNamedReceiver("css"); -``` - -As seen above the **target** names are **case-insensitive** and `-` are collapsed to cater for JavaScript/CSS naming conventions. - -## ServiceStack.Redis - -### Redis Pub/Sub Server - -To power RedisServerEvents we've extracted the managed Pub/Sub long-running message-loop originally built for [Redis MQ](https://github.com/ServiceStack/ServiceStack/wiki/Messaging-and-Redis) and encapsulated it into a re-usable class that can be used independently for handling messages published to specific [Redis Pub/Sub](http://redis.io/commands#pubsub) channels. - -`RedisPubSubServer` processes messages in a managed background thread that **automatically reconnects** when the redis-server connection fails and works like an independent background Service that can be stopped and started on command. - -The public API is captured in the [IRedisPubSubServer](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Redis/IRedisPubSubServer.cs) interface: - -```csharp -public interface IRedisPubSubServer : IDisposable -{ - IRedisClientsManager ClientsManager { get; } - // What Channels it's subscribed to - string[] Channels { get; } - - // Run once on initial StartUp - Action OnInit { get; set; } - // Called each time a new Connection is Started - Action OnStart { get; set; } - // Invoked when Connection is broken or Stopped - Action OnStop { get; set; } - // Invoked after Dispose() - Action OnDispose { get; set; } - - // Fired when each message is received - Action OnMessage { get; set; } - // Fired after successfully subscribing to the specified channels - Action OnUnSubscribe { get; set; } - // Called when an exception occurs - Action OnError { get; set; } - // Called before attempting to Failover to a new redis master - Action OnFailover { get; set; } - - int? KeepAliveRetryAfterMs { get; set; } - // The Current Time for RedisServer - DateTime CurrentServerTime { get; } - - // Current Status: Starting, Started, Stopping, Stopped, Disposed - string GetStatus(); - // Different life-cycle stats - string GetStatsDescription(); - - // Subscribe to specified Channels and listening for new messages - IRedisPubSubServer Start(); - // Close active Connection and stop running background thread - void Stop(); - // Stop than Start - void Restart(); -} -``` - -To use `RedisPubSubServer`, initialize it with the channels you want to subscribe to and assign handlers for each of the events you want to handle. At a minimum you'll want to handle `OnMessage`: - -```csharp -var clientsManager = new PooledRedisClientManager(); -var redisPubSub = new RedisPubSubServer(clientsManager, "channel-1", "channel-2") { - OnMessage = (channel, msg) => "Received '{0}' from '{1}'".Print(msg, channel) - }.Start(); -``` - -Calling `Start()` after it's initialized will get it to start listening and processing any messages published to the subscribed channels. - -## [App Settings](https://github.com/ServiceStack/ServiceStack/wiki/AppSettings) - -For many years our solution against using .NET's complex XML configuration for App configuration is to store structured configuration in the **Web.config** appSettings which thanks to the [JSV Format](https://github.com/ServiceStack/ServiceStack.Text/wiki/JSV-Format) makes it easy to read and write structured data from a single string value, e.g: - -```xml - - - - - - - -``` - -This can be easily parsed into C# types with the [IAppSettings](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Configuration/IAppSettings.cs) API: - -```csharp -IAppSettings settings = new AppSettings(); - -string value = settings.Get("String"); -int value = settings.Get("Int", defaultValue:1); -List values = settings.GetList("List"); -Dictionary valuesMap = settings.GetDictionary("Dict"); -MyConfig config = settings.Get("Poco", new MyConfig { Foo = "Baz" }); -``` - -Like other ServiceStack providers, `IAppSettings` is a clean interface with multiple providers letting you easily change or override where you want to source your App configuration from: - - - **DictionarySettings** - Maintain settings in an in-memory Dictionary - - **TextFileSettings** - Maintain settings in a plain-text file - - **OrmLiteAppSettings** - Maintain settings in any RDBMS `Config` table - -We take advantage of this in our [public OSS projects](https://github.com/ServiceStackApps/Chat) when we want to override [public appSettings with production settings](https://github.com/ServiceStackApps/HttpBenchmarks/blob/master/src/BenchmarksAnalyzer/Global.asax.cs#L29-L32) or in our [stand-alone Applications](https://github.com/ServiceStack/ServiceStack.Gap) by allowing us to ship our applications with more end-user friendly **plain-text config file** whose defaults are embedded in the stand-alone **.exe**, exporting it if it doesn't exist - letting us achieve a single, portable **.exe** that can be xcopy'ed and run as-is. - -### First class AppSettings - -After proving its value over the years we've decided to make it a first-class property on `IAppHost.AppSettings` which defaults to looking at .NET's App/Web.config's. - -The new [Chat.zip](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/Chat.zip) App explores different ways AppSettings can be used: - -If there's an existing `appsettings.txt` file where the **.exe** is run it will use that, otherwise it falls back to **Web.config** appSettings: - -```csharp -public AppHost() : base("Chat", typeof (ServerEventsServices).Assembly) -{ - var customSettings = new FileInfo("appsettings.txt"); - AppSettings = customSettings.Exists - ? (IAppSettings)new TextFileSettings(customSettings.FullName) - : new AppSettings(); -} -``` - -As a normal property in your AppHost, AppSettings can be accessed directly in `AppHost.Configure()`: - -```csharp -public void Configure(Container container) -{ - ... - var redisHost = AppSettings.GetString("RedisHost"); - if (redisHost != null) - { - container.Register(c => - new RedisServerEvents(new PooledRedisClientManager(redisHost))); - - container.Resolve().Start(); - } -} -``` - -Inside your services or IOC dependencies, like any other auto-wired dependency: - -```csharp -public class ServerEventsServices : Service -{ - public IAppSettings AppSettings { get; set; } - - public void Any(PostRawToChannel request) - { - if (!IsAuthenticated && AppSettings.Get("LimitRemoteControlToAuthenticatedUsers", false)) - throw new HttpError(HttpStatusCode.Forbidden, "You must be authenticated to use remote control."); - ... - } -} -``` - -Directly within Razor views: - -```html - -``` - -As well as outside ServiceStack, via the `HostContext` static class: - -```csharp -var redisHost = HostContext.AppSettings.GetString("redis"); -``` - -### AppSettings are now writable - -A new `Set()` API was added to [IAppSettings](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Configuration/IAppSettings.cs) letting you save any serializable property that works for all providers: - -```csharp -public interface IAppSettings -{ - void Set(string key, T value); - ... -} - -AppSettings.Set("Poco", new MyConfig { Foo = "Baz" }); -``` - -In providers that support writable configuration natively like `OrmLiteAppSettings` and `DictionarySettings`, the settings get written through to the underlying provider. For read-only providers like Web.config's `AppSettings` or `TextFileSettings` a **shadowed** cache is kept that works similar to prototypal shadowing in JavaScript where if a property doesn't exist, setting a property will be stored on the top-level object instance which also takes precedence on subsequent property access. - -## [Metadata Pages](https://github.com/ServiceStack/ServiceStack/wiki/Metadata-Page) - -The metadata pages have been expanded to include some of [Swagger API Attribute annotations](https://github.com/ServiceStack/ServiceStack/wiki/Swagger-API#swagger-attributes) which now shows the parameters for the Request and Response DTO's as well as any other DTO's used in each metadata operation page: - -![Metadata Type Info](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/metadata-swagger-api.png) - -When annotated the Description also shows any **allowable Enum values** or **range limits** when provided. - -#### HtmlFormat - -The humanize feature in [Auto HtmlFormat](https://github.com/ServiceStack/ServiceStack/wiki/HTML5ReportFormat) for splitting JoinedCase words with spaces can be disabled for all pages with: - -```csharp -HtmlFormat.Humanize = false; -``` - -Or on adhoc pages by adding `#dehumanize` hash param. - -## [Authentication](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization) - -### Web Sudo - -A common UX in some websites is to add an extra layer of protection for **super protected** functionality by getting users to re-confirm their password verifying it's still them using the website, common in places like confirming a financial transaction. - -**WebSudo** (by [@tvjames](https://github.com/tvjames)) is a new feature similar in spirit requiring users to re-authenticate when accessing Services annotated with the `[WebSudoRequired]` attribute. To make use of WebSudo, first register the plugin: - -```csharp -Plugins.Add(new WebSudoFeature()); -``` - -You can then apply WebSudo behavior to existing services by annotating them with `[WebSudoRequired]`: - -```csharp -[WebSudoRequired] -public class RequiresWebSudoService : Service -{ - public object Any(RequiresWebSudo request) - { - return request; - } -} -``` - -Once enabled this will throw a **402 Web Sudo Required** HTTP Error the first time the service is called: - -```csharp -var requiresWebSudo = new RequiresWebSudo { Name = "test" }; -try -{ - client.Send(requiresWebSudo); //throws -} -catch (WebServiceException) -{ - client.Send(authRequest); //re-authenticate - var response = client.Send(requiresWebSudo); //success! -} -``` - -Re-authenticating afterwards will allow access to the WebSudo service. - -### Auth Events - -In order to enable functionality like **WebSudo** we've added additional hooks into the Authentication process with `IAuthEvents`: - -```csharp -public interface IAuthEvents -{ - void OnRegistered(IRequest httpReq, IAuthSession session, IServiceBase registrationService); - - void OnAuthenticated(IRequest httpReq, IAuthSession session, IServiceBase authService, - IAuthTokens tokens, Dictionary authInfo); - - void OnLogout(IRequest httpReq, IAuthSession session, IServiceBase authService); - - void OnCreated(IRequest httpReq, IAuthSession session); -} -``` - -These are the same authentication hooks that were previously only available when creating a **Custom UserSession** by inheriting [AuthUserSession](https://github.com/ServiceStack/ServiceStack/wiki/Sessions#session-events). The new AuthEvents API provide a loose-typed way where plugins can tap into the same hooks by registering it with `AuthFeature.AuthEvents`, e.g: - -```csharp -public class WebSudoFeature : IPlugin, IAuthEvents -{ - public void Register(IAppHost appHost) - { - ... - var authFeature = appHost.GetPlugin(); - authFeature.AuthEvents.Add(this); - } - - // Add implementations on `IAuthEvents` handlers - public void OnCreated(IRequest httpReq, IAuthSession session) - { - ... - } - ... -} -``` - -An alternative way for accessing `IAuthEvents` is to register it like a normal dependency, e.g: - -```csharp -container.RegisterAs(); -``` - -To simplify custom implementations you can inherit from the empty concrete [AuthEvents](https://github.com/ServiceStack/ServiceStack/blob/7eb3a34a2e545a54c2591665328c16c5d398d37a/src/ServiceStack/Auth/AuthEvents.cs#L18-L25) and choose to only implement the callbacks you're interested in, e.g: - -```csharp -public class LogAuthEvents : AuthEvents -{ - public static ILog Log = LogManager.GetLogger(typeof(LogAuthEvents)); - - public override void OnLogout(IRequest httpReq, IAuthSession session, IServiceBase authService) - { - Log.DebugFormat("User #{0} {1} has logged out", session.UserAuthId, session.UserName); - } -} -``` - -## OrmLite - - - Added new `db.ColumnLazy` API for lazily fetching a column of data - - Added `db.TableExists` for a typed API to detect whether a table exists - - Added `INamingStrategy.GetSequenceName()` to [override how sequence names in Oracle are generated](http://stackoverflow.com/a/25611452/85785) - - Upgraded PostgreSql Provider to **Npgsql 2.2.0** and Sqlite to **Sqlite.Core 1.0.93.0** - -## Text - - - Added `JsConfig.ParsePrimitiveIntegerTypes` and `JsConfig.ParsePrimitiveFloatingPointTypes` to [change preferences on what primitive numeric types should be converted to](https://github.com/ServiceStack/ServiceStack.Text/pull/428). - - Added `JsConfig.IgnoreAttributesNamed` to [change what attributes are used to ignore properties](https://github.com/ServiceStack/ServiceStack.Text/commit/3b9972fbd61ce000f9af72d74d79b30eb0d2f45b) - - Added [string.CountOccurancesOf() extension method](https://github.com/ServiceStack/ServiceStack.Text/commit/d41d7fb879d68e5a4ccb529e3cc6ed7d3ce937a2) - - Added [Image MimeTypes](https://github.com/ServiceStack/ServiceStack.Text/commit/b07cf033d7b4735b0249850769b119be0c857b9d) - -## Community - -## [ServiceStack MiniProfiler Toolkit](https://bitbucket.org/migajek/miniprofilingtoolkit) - -From the wider ServiceStack Community, [Michał Gajek](https://plus.google.com/u/0/+Micha%C5%82Gajek/auto) has developed an alternative analyzer of ServiceStack's MiniProfiler results in a comprehensive UI that allows deep introspection of your running Services. From the Project's description: - -### Description - -This project intends to provide tools for collecting & analyzing profiling results of ServiceStack-based apps. -Not only this makes profiling possible in the scenario when no built-in web-frontend is available (like Single Page Applications), but also has several advantages over it: - - - collects & persists the results - - allows the "background" profiling (example: production environment) - - it's better to analyze large amounts of collected profiling results, not just focusing on single execution timings - - helps finding time-consuming queries - -### Screenshots - -![](http://i.imgur.com/Ybpx4xg.png) - -![](http://i.imgur.com/BA4Mc68.png) - -![](http://i.imgur.com/US4Gk6s.png) - -![](http://i.imgur.com/bILdbQc.png) - - -### Install - -``` -PM> Install-Package Migajek.MiniProfiling.ServiceStack.RemoteStorage -``` - -### Register the Plugin: - -```csharp -Plugins.Add(new Migajek.Profiling.ServiceStackProfiler.MiniProfilingToolkit("http://url/", "ProjectName")); -``` - -# v4.0.30 Release Notes - -## [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) - -We have an exciting feature in this release showcasing our initial support for generating Native Types from client VS.NET projects using [ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project#step-1-download-and-install-servicestackvs) new **Add ServiceStack Reference** feature. It provides a simpler, cleaner and more versatile alternative to WCF's **Add Service Reference** in VS.NET. - -Our goal with Native Types is to provide an alternative for sharing DTO dlls, that can enable a better dev workflow for external clients who are now able to generate (and update) Typed APIs for your Services from a remote url - reducing the burden and effort required to consume ServiceStack Services whilst benefiting from clients native language strong-typing feedback. - -This is just the beginning, whilst C# is the first language supported it lays the groundwork and signals our approach on adding support for typed API's in other languages in future. Add a [feature request for your favorite language](http://servicestack.uservoice.com/forums/176786-feature-requests) to prioritize support for it sooner! - -### Example Usage - -The easiest way to Add a ServiceStack reference to your project is to right-click on your project to bring up [ServiceStackVS's](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) `Add ServiceStack Reference` context-menu item. This opens a dialog where you can add the url of the ServiceStack instance you want to typed DTO's for, as well as the name of the T4 template that's added to your project. - -![Add ServiceStack Reference](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/add-service-ref-flow.png) - -After clicking OK, the servers DTO's and [ServiceStack.Client](https://www.nuget.org/packages/ServiceStack.Client) NuGet package are added to the project, providing an instant typed API: - -![Calling ServiceStack Service](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/call-service.png) - -### Consuming Services from Mobile Clients now Easier than Ever! - -In addition with our improved PCL Support in this release, it's never been easier to create an instant Typed API for a remote Service consumable from any Xamarin.Android, Xamarin.iOS, Silverlgiht 5, Windows Store or .full NET4.0+ platforms - Here's a quick demo of it working in Android: - -![Android Add ServiceStack Reference](https://raw.githubusercontent.com/ServiceStack/ServiceStackVS/master/Images/android-add-ref-demo.gif) - -### Advantages over WCF - - - **Simple** Uses a small T4 template to save generated POCO Types. Updating as easy as re-running T4 template - - **Versatile** Clean DTOs works in all JSON, XML, JSV, MsgPack and ProtoBuf [generic service clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client#built-in-clients) - - **Reusable** Generated DTO's are not coupled to any endpoint or format. Defaults are both partial and virtual for maximum re-use - - **Resilient** Messaging-based services offer a number of [advantages over RPC Services](https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services) - - **Flexible** DTO generation is customizable, Server and Clients can override built-in defaults - - **Integrated** Rich Service metadata annotated on DTO's, [Internal Services](https://github.com/ServiceStack/ServiceStack/wiki/Restricting-Services) are excluded when accessed externally - -### Available from v4.0.30+ ServiceStack Projects - -Native Types is now available by default on all **v4.0.30+** ServiceStack projects. It can be disabled by removing the `NativeTypesFeature` plugin with: - -```csharp -Plugins.RemoveAll(x => x is NativeTypesFeature); -``` - -For detailed info on how NativeTypesFeature works, its different customization options and improvements over WCF, checkout the [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) docs. - -### [Upgrade ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) - -To take advantage of this feature [Upgrade or Install ServiceStackVS](https://github.com/ServiceStack/ServiceStack/wiki/Creating-your-first-project) VS.NET Extension. If you already have **ServiceStackVS** installed, uninstall it first from `Tools -> Extensions and Updates... -> ServiceStackVS -> Uninstall`. - -## Improved PCL Story - -Our [PCL Story](https://github.com/ServiceStackApps/HelloMobile) has been greatly improved in this release now that `ServiceStack.Interfaces` has been converted into a pure PCL dll. This now lets you maintain your server DTO's in a pure PCL DLL that can be shared as-is on most supported platforms (Profile136): - - - Xamarin.iOS - - Xamarin.Android - - Windows Store - - WPF app using .NET 4.0 PCL support - - Silverlight 5 - -Whilst our impl-free `ServiceStack.Interfaces.dll` was able to be converted into a pure PCL dll, our Client libraries have instead resorted to using [PCL's Bait and Switch technique](http://log.paulbetts.org/the-bait-and-switch-pcl-trick/) to provide platform-specific extensions and optimizations. The one outlier is Silverlight5 which remains a custom (non-PCL) SL5 build, that whilst can now share DTO's, still can't support projects with dependencies on the PCL-compatible version of **ServiceStack.Client**. - -As of this release all PCL, platform and Silverlight dlls are now merged into the main [ServiceStack.Client](https://www.nuget.org/packages/ServiceStack.Client) NuGet packages so now any clients need only reference the main Client NuGet package: - -``` -Install-Package ServiceStack.Client -``` - -The [Hello PCL](https://github.com/ServiceStackApps/HelloMobile) project now contains examples of reusing a Server DTO project with all supported client platforms as well as showing re-use of a high-level `SharedGateway` which referenes `ServiceStack.Client` that's shared between all PCL-compatible platforms. - -### New ServiceStack + AngularJS Example - [StackApis](http://stackapis.servicestack.net) - -[![StackApis Home](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/stackapis-home.png)](http://stackapis.servicestack.net/) - -[StackApis](http://stackapis.servicestack.net/) is a simple new ServiceStack + AngularJS example project created with [ServiceStackVS AngularJS Template](https://github.com/ServiceStack/ServiceStackVS#servicestackvs) showcasing how quick and easy it is to create responsive feature-rich Single Page Apps with AngularJS and [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query). StackApis is powered by a Sqlite database containing [snapshot of ServiceStack questions from StackOverflow APIs](https://github.com/ServiceStackApps/StackApis/blob/master/src/StackApis.Tests/UnitTests.cs#L67) that's [persisted in an sqlite database](https://github.com/ServiceStackApps/StackApis/blob/master/src/StackApis.Tests/UnitTests.cs#L119-L124) using [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite/). - -### StackApis AutoQuery Service - -The [Home Page](https://github.com/ServiceStackApps/StackApis/blob/master/src/StackApis/default.cshtml) is built with less than **<50 Lines** of JavaScript which thanks to [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) routes all requests to the single AutoQuery Service below: - -```csharp -[Route("/questions")] -public class StackOverflowQuery : QueryBase -{ - public int? ScoreGreaterThan { get; set; } -} -``` - -> Not even `ScoreGreaterThan` is a required property, it's just an example of a [formalized convention](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query#advantages-of-well-defined-service-contracts) enabling queries from Typed Service Clients. - -Feel free to play around with a deployed version of StackApis at [stackapis.servicestack.net](http://stackapis.servicestack.net/). - -You can also use the public `http://stackapis.servicestack.net/` url to test out ServiceStack's new **Add ServiceStack Reference** feature :) - -## [Swagger Support](https://github.com/ServiceStack/ServiceStack/wiki/Swagger-API) - -### All static resources are now embedded - -ServiceStack's [Swagger Support](https://github.com/ServiceStack/ServiceStack/wiki/Swagger-API) received some welcomed enhancements thanks to [@tvjames](https://github.com/tvjames) and [@tyst](https://github.com/tyst)'s efforts which now sees all of Swagger's static resources embedded into a single `ServiceStack.Api.Swagger.dll`, taking advantage of the Virtual File Systems [transparent support for Embedded Resources](https://github.com/ServiceStack/ServiceStack.Gap#creating-an-embedded-servicestack-app), making it easier to manage and upgrade Swagger as a self-contained unit. - -### New Bootstrap theme for Swagger - -A new attractive Bootstrap Theme was also added to Swagger, available from [/swagger-ui-bootstrap/](http://stackapis.servicestack.net/swagger-ui-bootstrap/): - -[![Swagger Bootstrap](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/apps/StackApis/stackapis-swagger-bootstrap.png)](http://stackapis.servicestack.net/swagger-ui-bootstrap/) - -You can change the [metadata page plugin link](https://github.com/ServiceStack/ServiceStack/wiki/Metadata-page#adding-links-to-metadata-page) to point to this new theme with: - -```csharp -Plugins.Add(new SwaggerFeature { - UseBootstrapTheme = true, - LogoUrl = "your-logo.png" //optional use your own logo -}); -``` - -Swagger was also been updated to the latest version. - -## Authentication - -### Unique Emails - -ServiceStack now verifies emails returned by OAuth providers are now unique where if there's already another UserAuth with an existing email, authentication will fail and redirect (for HTML/Web Browser requests) with the Error token: - - /#f=EmailAlreadyExists - -This behavior is in-line with ServiceStack's other AuthProviders. If this change causes any issues, it can be disabled with: - -```csharp -AuthProvider.ValidateUniqueEmails = false; -``` - -> This doesn't apply to Users who login with multiple OAuth Providers as there accounts automatically get merged into a single UserAuth entity. - -### CustomValidationFilter - -A new `CustomValidationFilter` was added to all AuthProviders which can be used to return a `IHttpResult` to control what error response is returned, e.g: - -```csharp -Plugins.Add(new AuthFeature( - () => new CustomUserSession(), - new IAuthProvider[] { - new FacebookAuthProvider(appSettings) { - CustomValidationFilter = authCtx => - CustomIsValid(authCtx) - ? authCtx.Service.Redirect(authCtx.Session.ReferrerUrl - .AddHashParam("f","CustomErrorCode")) - : null, - }, - })); -``` - -## Breaking Changes - -### Upgrade all ServiceStack NuGet packages - -The primary breaking change was converting ServiceStack's core `ServiceStack.Interfaces.dll` into a pure portable class library which as it's incompatible with the previous non-PCL ServiceStack.Interfaces.dll requires that all NuGet dependenices (inc. transitive dependencies) be upgraded to **v4.0.30**. The version number was bumped to **v4.0.30** specifically to stress that it's incompatible with any ** - -Chat is another ServiceStack Single Page App Special showing how you can get a lot done with minimal effort and dependencies which delivers all these features in a tiny footprint built with vanilla jQuery and weighing just: - - - [1 default.cshtml page](https://github.com/ServiceStackApps/Chat/blob/master/src/Chat/default.cshtml) with under **170 lines of JavaScript** and **70 lines** of HTML - - [2 ServiceStack Services](https://github.com/ServiceStackApps/Chat/blob/master/src/Chat/Global.asax.cs) entire backend in 1 `.cs` file - - 1 ASP.NET Web Application project requiring only a sane **9 .NET dll** references - -### Remote control - -Chat features the ability to remotely control other users chat window with the client bindings in `/js/ss-utils.js`, providing a number of different ways to interact and modify a live webapp by either: - - - Invoking Global Event Handlers - - Modifying CSS via jQuery - - Sending messages to Receivers - - Raising jQuery Events - -All options above are designed to integrate with an apps existing functionality by providing the ability to invoke predefined handlers and exported object instances as well as modify jQuery CSS and raising DOM events. - -The [complete documentation](https://github.com/ServiceStackApps/Chat) in Chat is the recommended way to learn more about Server Events which goes through and explains how to use its Server and Client features. - -## [ServiceStackVS](https://github.com/ServiceStack/ServiceStackVS) - ServiceStack's VS.NET Extension - -Another exciting announcement is the initial release of [ServiceStackVS](https://github.com/ServiceStack/ServiceStackVS) - our VS.NET ServiceStack Extension containing the most popular starting templates for ServiceStack powered solutions: - -![Visual Studio Templates](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackvs/vs-templates.png) - -Each project template supports our [recommended multi-project structure](https://github.com/ServiceStack/ServiceStack/wiki/Physical-project-structure) promoting a clean architecture and Web Services best-practices, previously [documented in Email Contacts](https://github.com/ServiceStack/EmailContacts/#creating-emailcontacts-solution-from-scratch). - -This is now the fastest way to get up and running with ServiceStack. With these new templates you can now create a new ServiceStack Razor, AngularJS and Bootstrap enabled WebApp, pre-wired end-to-end in seconds: - -![AngularJS WalkThrough](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackvs/angularjs-overview.gif) - - - -### Get the [Learning AngularJS for .NET Developers](http://www.packtpub.com/learning-angularjs-for-net-developers/book) Book! - -On ServiceStack and AngularJS front, we also have great content coming from the ServiceStack community as -**[Learning AngularJS for .NET Developers](http://www.packtpub.com/learning-angularjs-for-net-developers/book)**, -a new book by [Alex Pop](https://twitter.com/AlexandruVPop) has just been made available. - -More details about the book as well as downloadable code-samples is available on -[Alex's announcement blog post](http://alexvpop.blogspot.co.uk/2014/06/announcing-learning-angularjs-dotnet.html). - -### Download ServiceStackVS - -ServiceStackVS supports both VS.NET 2013 and 2012 and can be [downloaded from the Visual Studio Gallery](http://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) - -[![VS.NET Gallery Download](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackvs/vsgallery-download.png)](http://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) - -### VS.NET 2012 Prerequisites - - - VS.NET 2012 Users must install the [Microsoft Visual Studio Shell Redistributable](http://www.microsoft.com/en-au/download/details.aspx?id=40764) - - It's also highly recommended to [Update to the latest NuGet](http://docs.nuget.org/docs/start-here/installing-nuget). - -> Alternatively if continuing to use an older version of the **NuGet Package Manager** you will need to click on **Enable NuGet Package Restore** after creating a new project to ensure its NuGet dependencies are installed. - -### Feedback - -We hope **ServiceStackVS** helps make ServiceStack developers more productive than ever and we'll look at continue improving it with new features in future. [Suggestions and feedback are welcome](http://servicestack.uservoice.com/forums/176786-feature-requests). - -## [Authentication](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization) - -### Saving User Profile Images - -To make it easier to build Social Apps like [Chat](https://github.com/ServiceStackApps/Chat) with ServiceStack we've started saving profile image urls (aka avatars) for the following popular OAuth providers: - - - Twitter - - Facebook - - GitHub - - Google OAuth2 - - LinkedIn OAuth2 - -The users profile url can be accessed in your services using the `IAuthSession.GetProfileUrl()` extension method which goes through the new `IAuthMetadataProvider` which by default looks in `UserAuthDetails.Items["profileUrl"]`. - -### New IAuthMetadataProvider - -A new [IAuthMetadataProvider](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/AuthMetadataProvider.cs) has been added that provides a way to customize the `authInfo` in all AuthProviders. It also allows overriding of how extended Auth metadata like `profileUrl` is returned. - -```csharp -public interface IAuthMetadataProvider -{ - void AddMetadata(IAuthTokens tokens, Dictionary authInfo); - - string GetProfileUrl(IAuthSession authSession, string defaultUrl = null); -} -``` - -> To override with a custom implementation, register `IAuthMetadataProvider` in the IOC - -### Saving OAuth Metadata - - -The new `SaveExtendedUserInfo` property (enabled by default) on all OAuth providers let you control whether to save the extended OAuth metadata available (into `UserAuthDetails.Items`) when logging in via OAuth. - -## [OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite/) - -### Loading of References in Multi-Select Queries - -Previous support of pre-loading of references were limited to a single entity using `LoadSingleById` to automatically fetch all child references, e.g: - -```csharp -public class Customer -{ - [AutoIncrement] - public int Id { get; set; } - public string Name { get; set; } - - [Reference] // Save in CustomerAddress table - public CustomerAddress PrimaryAddress { get; set; } - - [Reference] // Save in Order table - public List Orders { get; set; } -} - -var customer = db.LoadSingleById(request.Id); -customer.PrimaryAddress // Loads 1:1 CustomerAddress record -customer.Orders // Loads 1:M Order records -``` - -We've now also added support for pre-loading of references for multiple resultsets as well with `LoadSelect` which loads references for all results, e.g: - -```csharp -var customers = db.LoadSelect(q => q.Name.StartsWith("A")); -``` - -This is implemented efficiently behind the scenes where only 1 additional SQL Query is performed for each defined reference. - -> As a design goal none of OrmLite Query API's perform N+1 queries. - -### Self References - -We've extended OrmLite [References support](https://github.com/ServiceStack/ServiceStack.OrmLite/#reference-support-poco-style) to support Self References for **1:1** relations where the foreign key property can be on the parent table, e.g: - -```csharp -public class Customer -{ - ... - public int CustomerAddressId { get; set; } - - [Reference] - public CustomerAddress PrimaryAddress { get; set; } -} -``` - -Which maintains the same relationship as having the Foreign Key column on the child table instead, i,e: - -```csharp -public class CustomerAddress -{ - public int CustomerId { get; set; } -} -``` - -### Support Foreign Key Attributes to specify Reference Fields - -Previously definitions of references relied on [Reference Conventions](https://github.com/ServiceStack/ServiceStack.OrmLite/#reference-conventions) using either the C# Property Name or Property Aliases. You can now also use the [References and ForeignKey attributes](https://github.com/ServiceStack/ServiceStack.OrmLite/#new-foreign-key-attribute-for-referential-actions-on-updatedeletes) to specify Reference Properties, e.g: - -```csharp -public class Customer -{ - [Reference(typeof(CustomerAddress))] - public int PrimaryAddressId { get; set; } - - [Reference] - public CustomerAddress PrimaryAddress { get; set; } -} -``` - -> Reference Attributes take precedence over naming conventions - -### Support for Stored Procedures with out params - -A new `SqlProc` API was added returning an `IDbCommand` which can be used to customize the Stored Procedure call letting you add custom out parameters. The example below shows - -```csharp -string spSql = @"DROP PROCEDURE IF EXISTS spSearchLetters; - CREATE PROCEDURE spSearchLetters (IN pLetter varchar(10), OUT pTotal int) - BEGIN - SELECT COUNT(*) FROM LetterFrequency WHERE Letter = pLetter INTO pTotal; - SELECT * FROM LetterFrequency WHERE Letter = pLetter; - END"; - -db.ExecuteSql(spSql); - -var cmd = db.SqlProc("spSearchLetters", new { pLetter = "C" }); -var pTotal = cmd.AddParam("pTotal", direction: ParameterDirection.Output); - -var results = cmd.ConvertToList(); -var total = pTotal.Value; -``` - -An alternative approach is to use the new overload added to the raw SQL API `SqlList` that lets you customize the Stored Procedure using a filter, e.g: - -```csharp -IDbDataParameter pTotal = null; -var results = db.SqlList("spSearchLetters", cmd => { - cmd.CommandType = CommandType.StoredProcedure; - cmd.AddParam("pLetter", "C"); - pTotal = cmd.AddParam("pTotal", direction: ParameterDirection.Output); - }); -var total = pTotal.Value; -``` - -### Minor OrmLite Features - - - Use `OrmLiteConfig.DisableColumnGuessFallback=false` to disable fallback matching heuristics - - Added [GenericTableExpressions](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/Expression/GenericTableExpressions.cs) example showing how to extend OrmLite to support different runtime table names on a single schema type. - -## [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) - -### Support for loading References - -AutoQuery now takes advantage of OrmLite's new support for loading child references where marking your Query DTO with `[Reference]` will automatically load its related data, e.g: - -```csharp -public class Rockstar -{ - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public int? Age { get; set; } - - [Reference] - public List Albums { get; set; } -} -``` - -### Improved OrderBy - -Add support for inverting sort direction of individual orderBy fields using '-' prefix e.g: - -```csharp -// ?orderBy=Rating,-ImdbId -var movies = client.Get(new SearchMovies { OrderBy = "Rating,-ImdbId" }); - -// ?orderByDesc=-Rating,ImdbId -var movies = client.Get(new SearchMovies { OrderByDesc = "-Rating,ImdbId" }); -``` - -## ServiceStack.Text - - - Added support for `OrderedDictionary` and other uncommon `IDictionary` types - - WCF-style `JsConfig.OnSerializedFn` custom hook has been added - - `JsConfig.ReuseStringBuffer` is enabled by default for faster JSON/JSV text serialization - - Properties can also be ignored with `[JsonIgnore]` attribute - -## Other Features - - - New `[Exclude(Feature.Soap)]` attribute can be used to exclude types from XSD/WSDL's - - XSD/WSDL's no longer including open generic types - - Added `$.ss.getSelection()`, `$.ss.queryString()`, `$.ss.splitOnFirst()`, `$.ss.splitOnLast()` to /ss-utils.js - - `TwitterAuthProvider` now makes authenticated v1.1 API requests to fetch user metadata - - -# v4.0.23 Release Notes - -## [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) - -The big ticket feature in this release is the new [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) feature - with our approach of enabling Queryable Data Services, that's designed to avoid [OData's anti-patterns and pitfalls](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query#why-not-odata). - - - Simple, intuitive and easy to use! - - Works with all OrmLite's [supported RDBMS providers](https://github.com/ServiceStack/ServiceStack.OrmLite/#download) - - Supports multiple table JOINs and custom responses - - Code-first, declarative programming model - - Promotes clean, intent-based self-describing API's - - Highly extensible, implementations are completely overridable - - Configurable Adhoc, Explicit and Implicit conventions - - Allows preemptive client queries - - New `GetLazy()` API in Service Clients allow transparently streaming of paged queries - - Raw SqlFilters available if required - -#### AutoQuery Services are normal ServiceStack Services - -AutoQuery also benefits from just being normal ServiceStack Services where you can re-use existing knowledge in implementing, customizing, introspecting and consuming ServiceStack services, i.e: - - - Utilizes the same customizable [Request Pipeline](https://github.com/ServiceStack/ServiceStack/wiki/Order-of-Operations) - - AutoQuery services can be mapped to any [user-defined route](https://github.com/ServiceStack/ServiceStack/wiki/Routing) - - Is available in all [registered formats](https://github.com/ServiceStack/ServiceStack/wiki/Formats) - - The [CSV Format](https://github.com/ServiceStack/ServiceStack/wiki/ServiceStack-CSV-Format) especially shines in AutoQuery who's tabular result-set are perfect for CSV - - Can be [consumed from typed Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/Clients-overview) allowing an end-to-end API without code-gen in [PCL client platforms as well](https://github.com/ServiceStackApps/HelloMobile) - -### Getting Started - -AutoQuery uses your Services existing OrmLite DB registration, the example below registers an InMemory Sqlite Provider: - -```csharp -container.Register( - new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider)); -``` - -There are no additional dependencies, enabling AutoQuery is as easy as registering the AutoQueryFeature Plugin: - -```csharp -Plugins.Add(new AutoQueryFeature { MaxLimit = 100 }); -``` - -The configuration above limits all queries to a maximum of **100** results. - -The minimum code to expose a Query Service for the `Rockstar` table under a user-defined Route is just: - -```csharp -[Route("/rockstars")] -public class FindRockstars : QueryBase {} -``` - -With no additional code, this allows you to use any of the registered built-in conventions, e.g: - - /rockstars?Ids=1,2,3 - /rockstars?AgeOlderThan=42 - /rockstars?AgeGreaterThanOrEqualTo=42 - /rockstars?FirstNameIn=Jim,Kurt - /rockstars?FirstNameBetween=A,F - /rockstars?FirstNameStartsWith=Jim - /rockstars?LastNameEndsWith=son - /rockstars?IdAbove=1000 - -You're also able to formalize your API by adding concrete properties to your Request DTO: - -```csharp -public class QueryRockstars : QueryBase -{ - public int? AgeOlderThan { get; set; } -} -``` - -Which now lets you access AutoQuery Services from the ServiceStack's [Typed Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client): - -```csharp -client.Get(new QueryRockstars { AgeOlderThan = 42 }); -``` - -You can also take advantage of the new `GetLazy()` API to transparently stream large result-sets in managable-sized chunks: - -```csharp -var results = client.GetLazy(new QueryMovies { Ratings = new[]{"G","PG-13"}}).ToList(); -``` - -As GetLazy returns a lazy `IEnumerable` sequence it can be used within LINQ expressions: - -```csharp -var top250 = client.GetLazy(new QueryMovies { Ratings = new[]{ "G", "PG-13" } }) - .Take(250) - .ConvertTo(x => x.Title); -``` - -This is just a sampler, for a more complete guide to AutoQuery checkout the [AutoQuery wiki](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query). - -## New VistaDB OrmLite Provider! - -Also in this release is a preview release of OrmLite's new support for [VistaDB](http://www.gibraltarsoftware.com/) thanks to the efforts of [Ilya Lukyanov](https://github.com/ilyalukyanov). - -[VistaDB](http://www.gibraltarsoftware.com/) is a commercial easy-to-deploy SQL Server-compatible embedded database for .NET that provides a good alternative to Sqlite for embedded scenarios. - -To use first download and install [VistaDB](http://www.gibraltarsoftware.com/) itself, then grab OrmLite's VistaDB provider from NuGet: - - PM> Install-Package ServiceStack.OrmLite.VistaDb - -Then register the VistaDB Provider and the filename of what embedded database to use with: - -```csharp -VistaDbDialect.Provider.UseLibraryFromGac = true; - -container.Register( - new OrmLiteConnectionFactory("Data Source=db.vb5;", VistaDbDialect.Provider)); -``` - -The VistaDB provider is almost a complete OrmLite provider, the one major missing feature is OrmLite's new support for [Optimistic Concurrency](https://github.com/ServiceStack/ServiceStack.OrmLite/#optimistic-concurrency) which is missing in VistaDB which doesn't support normal Database triggers but we're still researching the most optimal way to implement this in VistaDB. - -## Improved AspNetWindowsAuthProvider - -A new `LoadUserAuthFilter` was added to allow `AspNetWindowsAuthProvider` to retrieve more detailed information about Windows Authenticated users by using the .NET's ActiveDirectory services, e.g: - -```csharp -public void LoadUserAuthInfo(AuthUserSession userSession, - IAuthTokens tokens, Dictionary authInfo) -{ - if (userSession == null) return; - using (PrincipalContext pc = new PrincipalContext(ContextType.Domain)) - { - var user = UserPrincipal.FindByIdentity(pc, userSession.UserAuthName); - tokens.DisplayName = user.DisplayName; - tokens.Email = user.EmailAddress; - tokens.FirstName = user.GivenName; - tokens.LastName = user.Surname; - tokens.FullName = (String.IsNullOrWhiteSpace(user.MiddleName)) - ? "{0} {1}".Fmt(user.GivenName, user.Surname) - : "{0} {1} {2}".Fmt(user.GivenName, user.MiddleName, user.Surname); - tokens.PhoneNumber = user.VoiceTelephoneNumber; - } -} -``` - -Then to use the above custom filter register it in AspNetWindowsAuthProvider with: - -```csharp -Plugins.Add(new AuthFeature( - () => new CustomUserSession(), - new IAuthProvider[] { - new AspNetWindowsAuthProvider(this) { - LoadUserAuthFilter = LoadUserAuthInfo - } - )); -``` - -Above example kindly provided by [Kevin Howard](https://github.com/KevinHoward). - -## Other features - - - [OrmLite's T4 Templates](https://github.com/ServiceStack/ServiceStack.OrmLite/#t4-template-support) were improved by [Darren Reid](https://github.com/Layoric) - - ApiVersion added to Swaggers ResourcesResponse DTO - - `Uri` in RedisClient allows passwords - -# v4.0.22 Release Notes - -## OrmLite - -This was primarily an OrmLite-focused release with the introduction of major new features: - -### Typed SQL Expressions now support Joins! - -Another [highly requested feature](http://servicestack.uservoice.com/forums/176786-feature-requests/suggestions/4459040-enhance-ormlite-with-common-data-usage-patterns) has been realized in this release with OrmLite's typed SqlExpressions extended to add support for Joins. - -The new JOIN support follows OrmLite's traditional approach of a providing a DRY, typed RDBMS-agnostic wrapper that retains a high affinity with SQL, providing an intuitive API that generates predictable SQL and a light-weight mapping to clean POCO's. - -### Basic Example - -Starting with the most basic example you can simply specify the table you want to join with: - -```csharp -var dbCustomers = db.Select(q => q.Join()); -``` - -This query rougly maps to the following SQL: - -```sql -SELECT Customer.* - FROM Customer - INNER JOIN - CustomerAddress ON (Customer.Id == CustomerAddress.Id) -``` - -Just like before `q` is an instance of `SqlExpression` which is bounded to the base `Customer` type (and what any subsequent implicit API's apply to). - -To better illustrate the above query, lets expand it to the equivalent explicit query: - -```csharp -SqlExpression q = db.From(); -q.Join(); - -List dbCustomers = db.Select(q); -``` - -### Reference Conventions - -The above query joins together the `Customer` and `CustomerAddress` POCO's using the same relationship convention used in [OrmLite's support for References](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/LoadReferencesTests.cs), i.e. using the referenced table `{ParentType}Id` property convention. - -An example of what this looks like can be seen the POCO's below: - -```csharp -class Customer { - public Id { get; set; } - ... -} -class CustomerAddress { - public Id { get; set; } - public CustomerId { get; set; } // Reference based on Property name convention -} -``` - -References based on matching alias names is also supported, e.g: - -```csharp -[Alias("LegacyCustomer")] -class Customer { - public Id { get; set; } - ... -} -class CustomerAddress { - public Id { get; set; } - - [Alias("LegacyCustomerId")] // Matches `LegacyCustomer` Alias - public RenamedCustomerId { get; set; } // Reference based on Alias Convention -} -``` - -Either convention lets you save a POCO and all its entity references with `db.Save()`, e.g: - -```csharp -var customer = new Customer { - Name = "Customer 1", - PrimaryAddress = new CustomerAddress { - AddressLine1 = "1 Australia Street", - Country = "Australia" - }, -}; -db.Save(customer, references:true); -``` - -Going back to the above example: - -```csharp -q.Join(); -``` - -Uses the implicit join in the above reference convention to expand into the equivalent explicit API: - -```csharp -q.Join((customer,address) => customer.Id == address.CustomerId); -``` - -### Selecting multiple columns across joined tables - -Another behaviour implicit when selecting from a typed SqlExpression is that results are mapped to the `Customer` POCO. To change this default we just need to explicitly specify what POCO it should map to instead: - -```csharp -List customers = db.Select( - db.From().Join()); -``` - -Where `FullCustomerInfo` is any POCO that contains a combination of properties matching any of the joined tables in the query. - -The above example is also equivalent to the shorthand `db.Select()` API: - -```csharp -var customers = db.Select(q => q.Join()); -``` - -Rules for how results are mapped is simply each property on `FullCustomerInfo` is mapped to the first matching property in any of the tables in the order they were added to the SqlExpression. - -As most OrmLite tables have a primary key property named `Id`, the auto-mapping includes a fallback for mapping to a full namespaced Id property in the same `{Type}Id` format. This allows you to auto-populate `CustomerId`, `CustomerAddressId` and `OrderId` columns even though they aren't a match to any of the fields in any of the joined tables. - -### Advanced Example - -Seeing how the SqlExpression is constructed, joined and mapped, we can take a look at a more advanced example to showcase more of the new API's available: - -```csharp -List rows = db.Select( // Map results to FullCustomerInfo POCO - db.From() // Create typed Customer SqlExpression - .LeftJoin() // Implict left join with base table - .Join((c,o) => c.Id == o.CustomerId) // Explicit join and condition - .Where(c => c.Name == "Customer 1") // Implicit condition on base table - .And(o => o.Cost < 2) // Explicit condition on joined Table - .Or((c,o) => c.Name == o.LineItem)); // Explicit condition with joined Tables -``` - -The comments next to each line document each Type of API used. Some of the new API's introduced in this example include: - - - Usage of `LeftJoin` for LEFT JOIN'S, `RightJoin` and `FullJoin` also available - - Usage of `And()`, to specify a condition on a Joined table - - Usage of `Or`, to specify a condition against 2 joined tables - -More code examples of References and Joined tables are available in: - - - [LoadReferencesTests.cs](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/LoadReferencesTests.cs) - - [LoadReferencesJoinTests.cs](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/LoadReferencesJoinTests.cs) - -## Optimistic Concurrency - -Another major feature added to OrmLite is support for optimistic concurrency which can be added to any table by adding a `ulong RowVersion { get; set; }` property, e.g: - -```csharp -public class Poco -{ - ... - public ulong RowVersion { get; set; } -} -``` - -RowVersion is implemented efficiently in all major RDBMS's, i.e: - - - Uses `rowversion` datatype in SqlServer - - Uses PostgreSql's `xmin` system column (no column on table required) - - Uses UPDATE triggers on MySql, Sqlite and Oracle whose lifetime is attached to Create/Drop tables APIs - -Despite their differing implementations each provider works the same way where the `RowVersion` property is populated when the record is selected and only updates the record if the RowVersion matches with what's in the database, e.g: - -```csharp -var rowId = db.Insert(new Poco { Text = "Text" }, selectIdentity:true); - -var row = db.SingleById(rowId); -row.Text += " Updated"; -db.Update(row); //success! - -row.Text += "Attempting to update stale record"; - -//Can't update stale record -Assert.Throws(() => - db.Update(row)); - -//Can update latest version -var updatedRow = db.SingleById(rowId); // fresh version -updatedRow.Text += "Update Success!"; -db.Update(updatedRow); - -updatedRow = db.SingleById(rowId); -db.Delete(updatedRow); // can delete fresh version -``` - -Optimistic concurrency is only verified on API's that update or delete an entire entity, i.e. it's not enforced in partial updates. There's also an Alternative API available for DELETE's: - -```csharp -db.DeleteById(id:updatedRow.Id, rowversion:updatedRow.RowVersion) -``` - -### Other OrmLite features - - - New [Limit API's added to JoinSqlBuilder](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/Expression/SqlExpressionTests.cs#L126-L168) - - SqlExpression's are now tied to the dialect provider at time of creation - -## ServiceStack.Text - -A new `JsConfig.ReuseStringBuffer` performance config option is available to JSON and JSV Text Serializers which lets you re-use ThreadStatic StringBuilder when serializing to a string. In initial benchmarks (both synchronous and parallel) it shows around a **~%30 increase in performance** for small POCO's. It can be enabled with: - -```csharp -JsConfig.ReuseStringBuffer = true; -``` - -Default enum values can be excluded from being serialized with: - -```csharp -JsConfig.IncludeDefaultEnums = false; -``` - -## ServiceStack - -### [Messaging](https://github.com/ServiceStack/ServiceStack/wiki/Messaging) - -Improved support for the MQ Request/Reply pattern with the new `GetTempQueueName()` API now available in all MQ Clients which returns a temporary queue (prefixed with `mq:tmp:`) suitable for use as the ReplyTo queue in Request/Reply scenarios: - -```csharp -mqServer.RegisterHandler(m => - new HelloResponse { Result = "Hello, {0}!".Fmt(m.GetBody().Name) }); -mqServer.Start(); - -using (var mqClient = mqServer.CreateMessageQueueClient()) -{ - var replyToMq = mqClient.GetTempQueueName(); - mqClient.Publish(new Message(new Hello { Name = "World" }) { - ReplyTo = replyToMq - }); - - IMessage responseMsg = mqClient.Get(replyToMq); - mqClient.Ack(responseMsg); - var responseDto = responseMsg.GetBody(); -} -``` - -On [Rabbit MQ](https://github.com/ServiceStack/ServiceStack/wiki/Rabbit-MQ) it creates an exclusive non-durable queue. - -In [Redis MQ](https://github.com/ServiceStack/ServiceStack/wiki/Messaging-and-Redis) there's a new `RedisMqServer.ExpireTemporaryQueues()` API which can be used on StartUp to expire temporary queues after a given period. - -Synchronous and Parallel tests for this feature is available in [MqRequestReplyTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Server.Tests/Messaging/MqRequestReplyTests.cs). - -## New NuGet packages - - - [ServiceStack.Authentication.LightSpeed](https://www.nuget.org/packages/ServiceStack.Authentication.LightSpeed/) is a new User Auth Repository created by [Herdy Handoko](https://plus.google.com/u/0/+HerdyHandoko/posts) providing a new persistence option for User Authentication backed by [Mindscape's LightSpeed ORM](http://www.mindscapehq.com/products/lightspeed). Checkout the [GitHub Project](https://github.com/hhandoko/ServiceStack.Authentication.LightSpeed) for more info. - -### Other Framework Features - - - Added support for locking users in all AuthProviders by populating `UserAuth.LockedDate`, effective from next login attempt - - Reduced dependencies on all Logging providers, now only depends on `ServiceStack.Interfaces` - - ContentLength is written where possible allowing [Async Progress callbacks on new payloads](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/AsyncProgressTests.cs) - - Non authenticated requests to `/auth` throw a 401 (otherwise returns basic session info) - - Metadata filter now supports IE8/IE9 - - `CopyTo` and `WriteTo` Stream extensions now return bytes transferred - -# v4.0.21 Release Notes - -## Authentication - -### Windows Auth Provider for ASP.NET - -An ASP.NET WindowsAuth Provider preview is available. This essentially wraps the existing Windows Auth support baked into ASP.NET and adds an adapter for [ServiceStack's Multi-Provider Authentication model](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization). - -It can be registered just like any other Auth Provider, i.e. in the AuthFeature plugin: - -```csharp -Plugins.Add(new AuthFeature( - () => new CustomUserSession(), - new IAuthProvider[] { - new AspNetWindowsAuthProvider(this) { AllowAllWindowsAuthUsers = true }, - } -)); -``` - -By default it only allows access to users in `AspNetWindowsAuthProvider.LimitAccessToRoles`, but can be overridden with `AllowAllWindowsAuthUsers=true` to allow access to all Windows Auth users as seen in the example above. - -Credentials can be attached to ServiceStack's Service Clients the same way [as .NET WebRequest's](http://stackoverflow.com/a/3563033/85785) by assingning the `Credentials` property, e.g: - -```csharp -var client = new JsonServiceClient(BaseUri) { - Credentials = CredentialCache.DefaultCredentials, -}; - -var response = client.Get(new RequiresAuth { Name = "Haz Access!" }); -``` - -To help with debugging, [?debug=requestinfo](https://github.com/ServiceStack/ServiceStack/wiki/Debugging#request-info) has been extended to include the Request's current Logon User info: - -![WindowsAuth DebugInfo](https://github.com/ServiceStack/Assets/raw/master/img/release-notes/debuginfo-windowsauth.png) - -> We're interested in hearing future use-cases this can support, feedback on this and future integration with Windows Auth are welcomed on [the Active Directory Integration feature request](http://servicestack.uservoice.com/forums/176786-feature-requests/suggestions/4725924-built-in-active-directory-authentication-suport). - -### New GitHub and other OAuth Providers available - -Thanks to [Rouslan Grabar](https://github.com/iamruss) we now have a number of new OAuth providers built into ServiceStack, including authentication with GitHub, Russia's most popular search engine [Yandex](http://www.yandex.ru/) and Europe's largest Social Networks after Facebook, [VK](http://vk.com) and [Odnoklassniki](http://odnoklassniki.ru/): - -```csharp -Plugins.Add(new AuthFeature( - () => new CustomUserSession(), - new IAuthProvider[] { - new GithubAuthProvider(appSettings), - new YandexAuthProvider(appSettings), - new VkAuthProvider(appSettings), - new OdnoklassnikiAuthProvider(appSettings), - } -)); -``` - -### Extended Auth DTO's - -You can now test whether a user is authenticated by calling the Auth Service without any parameters, e.g. `/auth` which will return summary auth info of the currently authenticated user or a `401` if the user is not authenticated. A `DisplayName` property was added to `AuthenticateResponse` to return a friendly name of the currently authenticated user. - -## [Portable ServiceStack](https://github.com/ServiceStack/ServiceStack.Gap) - -A new [ServiceStack.Gap](https://github.com/ServiceStack/ServiceStack.Gap) Repository and NuGet package was added to help with creating ServiceStack-powered Desktop applications. - -ServiceStack has a number of features that's particularly well-suited for these kind of apps: - - - It allows your services to be self-hosted using .NET's HTTP Listener - - It supports pre-compiled Razor Views - - It supports Embedded resources - - It supports an embedded database in Sqlite and OrmLite - - It can be ILMerged into a single .exe - -Combined together this allows you to encapsulate your ServiceStack application into a single cross-platform .exe that can run on Windows or OSX. - -To illustrate the potential of embedded ServiceStack solutions, a portable version [httpbenchmarks.servicestack.net](https://httpbenchmarks.servicestack.net) was created targetting a number of platforms below: - -> **[BenchmarksAnalyzer.zip](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/BenchmarksAnalyzer.zip)** - Single .exe that opens the BenchmarksAnalyzer app in the users browser - -[![Partial Console Screenshot](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/gap/partial-exe.png)](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/BenchmarksAnalyzer.zip) - -> **[BenchmarksAnalyzer.Mac.zip](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/BenchmarksAnalyzer.Mac.zip)** - Self-hosted app running inside a OSX Cocoa App Web Browser - -[![Partial OSX Screenshot](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/gap/partial-osx.png)](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/BenchmarksAnalyzer.Mac.zip) - -> **[BenchmarksAnalyzer.Windows.zip](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/BenchmarksAnalyzer.Windows.zip)** - Self-hosted app running inside a Native WinForms app inside [CEF](https://code.google.com/p/chromiumembedded/) - -[![Partial Windows Screenshot](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/gap/partial-win.png)](https://github.com/ServiceStack/ServiceStack.Gap/raw/master/deploy/BenchmarksAnalyzer.Windows.zip) - -### Usage - -By default `BenchmarksAnalyzer.exe` will scan the directory where it's run from, it also supports being called with the path to `.txt` or `.zip` files to view or even a directory where output files are located. Given this there are a few popular ways to use Benchmarks Analyzer: - - - Drop `BenchmarksAnalyzer.exe` into a directory of benchmark outputs before running it - - Drop a `.zip` or folder onto the `BenchmarksAnalyzer.exe` to view those results - -> Note: It can also be specified as a command-line argument, e.g: "BenchmarksAnalyzer.exe path\to\outputs" - -![Benchmarks Analyzer Usage](https://github.com/ServiceStack/Assets/raw/master/img/gap/benchmarksanalyzer-usage.gif) - -### ServiceStack.Gap Developer Guide - -The guides on how each application was created is on [ServiceStack.Gap](https://github.com/ServiceStack/ServiceStack.Gap) site, i.e: - - - [Self-Hosting Console App](https://github.com/ServiceStack/ServiceStack.Gap#self-hosting-console-app) - - [Windows Forms App with Chromium Embedded Framework and CefSharp](https://github.com/ServiceStack/ServiceStack.Gap#winforms-with-chromium-embedded-framework) - - [Mac OSX Cocoa App with Xmarain.Mac](https://github.com/ServiceStack/ServiceStack.Gap#mac-osx-cocoa-app-with-xmarainmac) - -## Other Framework Features - -### Filtering support added to Metadata pages - -You can now filter services on ServiceStack's `/metadata` page: - -![Metadata Filter](https://github.com/ServiceStack/Assets/raw/master/img/release-notes/metadata-filter.png) - -### Typed Request Filters - -A more typed API to register Global Request and Response filters per Request DTO Type are available under the `RegisterTyped*` API's in AppHost. These can be used to provide more flexibility in multi-tenant solutions by attaching custom data on incoming requests, e.g: - -```csharp -public override void Configure(Container container) -{ - RegisterTypedRequestFilter((req, res, dto) => - { - var route = req.GetRoute(); - if (route != null && route.Path == "/tenant/{TenantName}/resource") - { - dto.SubResourceName = "CustomResource"; - } - }); -} -``` - -Typed Filters can also be used to apply custom behavior on Request DTO's sharing a common interface, e.g: - -```csharp -public override void Configure(Container container) -{ - RegisterTypedRequestFilter((req, res, dtoInterface) => { - dtoInterface.SharedProperty = "Is Shared"; - }); -} -``` - -### Buffered Stream option has now added to Response - -Response streams can be buffered in the same way as you can buffer Request streams by setting `UseBufferedStream=true`, e.g: - -```csharp -appHost.PreRequestFilters.Add((httpReq, httpRes) => { - httpReq.UseBufferedStream = true; - httpRes.UseBufferedStream = true; -}); - -``` - -### AfterInitCallbacks added to AppHost - -You can register callbacks to add custom logic straight after the AppHost has finished initializing. E.g. you can find all Roles specified in `[RequiredRole]` attributes with: - -```csharp -appHost.AfterInitCallbacks.Add(host => -{ - var allRoleNames = host.Metadata.OperationsMap - .SelectMany(x => x.Key.AllAttributes() - .Concat(x.Value.ServiceType.AllAttributes())) - .SelectMany(x => x.RequiredRoles); -}); -``` - -### Request Scopes can be configured to use ThreadStatic - -Request Scoped dependencies are stored in `HttpRequest.Items` for ASP.NET hosts and uses Remoting's `CallContext.LogicalData` API's in self-hosts. Using the Remoting API's can be problematic in old versions of Mono or when executed in test runners. - -If this is an issue the RequestContext can be configured to use ThreadStatic with: - -```csharp -RequestContext.UseThreadStatic = true; -``` - -### Logging - -Updated Logging providers to allow `debugEnabled` in their LogFactory constructor, e.g: - -```csharp -LogFactory.LogManager = new NullLogFactory(debugEnabled:false); -LogFactory.LogManager = new ConsoleLogFactory(debugEnabled:true); -LogFactory.LogManager = new DebugLogFactory(debugEnabled:true); -``` - -Detailed command logging is now enabled in OrmLite and Redis when `debugEnabled=true`. The external Logging provider NuGet packages have also been updated to use their latest version. - -### Razor - - - Enabled support for Razor `@helpers` and `@functions` in Razor Views - - Direct access to Razor Views in `/Views` is now denied by default - -### Service Clients - - - Change Silverlight to auto emulate HTTP Verbs for non GET or POST requests - - Shorter aliases added on `PostFileWithRequest` which uses the Request DTO's auto-generated url - - The [PCL version of ServiceStack.Interfaces](https://github.com/ServiceStackApps/HelloMobile) now supports a min version of .NET 4.0 - -## OrmLite - -### Exec and Result Filters - -A new `CaptureSqlFilter` Results Filter has been added which shows some of the power of OrmLite's Result filters by being able to capture SQL Statements without running them, e.g: - -```csharp -public class CaptureSqlFilter : OrmLiteResultsFilter -{ - public CaptureSqlFilter() - { - SqlFilter = CaptureSql; - SqlStatements = new List(); - } - - private void CaptureSql(string sql) - { - SqlStatements.Add(sql); - } - - public List SqlStatements { get; set; } -} -``` - -This can then be wrapped around existing database calls to capture and print the generated SQL, e.g: - -```csharp -using (var captured = new CaptureSqlFilter()) -using (var db = OpenDbConnection()) -{ - db.CreateTable(); - db.Count(x => x.Age < 50); - db.Insert(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix" }); - db.Delete(new { FirstName = "Jimi", Age = 27 }); - - var sql = string.Join(";\n", captured.SqlStatements.ToArray()); - sql.Print(); -} -``` - -#### Exec filters can be limited to specific Dialect Providers - -```csharp -OrmLiteConfig.DialectProvider.ExecFilter = execFilter; -``` - -### OrmLite's custom SqlBuilders now implement ISqlExpression - -OrmLite provides good support in integrating with external or custom SQL builders that implement OrmLite's simple `ISqlExpression` interface which can be passed directly to `db.Select()` API. This has now been added to OrmLite's other built-in SQL Builders, e.g: - -#### Using JoinSqlBuilder - -```csharp -var joinQuery = new JoinSqlBuilder() - .LeftJoin(x => x.Id, x => x.UserId, - sourceWhere: x => x.Age > 18, - destinationWhere: x => x.Country == "Italy"); - -var results = db.Select(joinQuery); -``` - -#### Using SqlBuilder - -```csharp -var tmpl = sb.AddTemplate( - "SELECT * FROM User u INNER JOIN Address a on a.UserId = u.Id /**where**/"); -sb.Where("Age > @age", new { age = 18 }); -sb.Where("Countryalias = @country", new { country = "Italy" }); - -var results = db.Select(tmpl, tmpl.Parameters); -``` - -### Other Changes - - - OrmLite can create tables with any numeric type in all providers. Fallbacks were added on ADO.NET providers that don't support the numeric type natively - - Load/Save Reference property conventions can be [inferred on either aliases or C# property names](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/LoadReferencesTests.cs#L207) - - OrmLite can create tables from types with Indexers - - Can use `OrmLiteConfig.StripUpperInLike=true` to [remove use of upper() in Sql Expressions](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/Expression/SelectExpressionTests.cs#L205) - -## Redis - -A new `TrackingRedisClientsManager` client manager has been added by [Thomas James](https://github.com/tvjames) to help diagnose Apps that are leaking redis connections. - -# v4.0.19 Release Notes - -## Embedded ServiceStack - -This release has put all the final touches together to open up interesting new use-cases for deploying ServiceStack solutions into a single self-contained, cross-platform, xcopy-able executable. - -By leveraging ServiceStack's support for [self-hosting](https://github.com/ServiceStack/ServiceStack/wiki/Self-hosting), the [Virtual File System](https://github.com/ServiceStack/ServiceStack/wiki/Virtual-file-system) support for Embedded Resources and the new support for [Compiled Razor Views](#compiled-razor-views), we can embed all images/js/css Razor views and Markdown Razor assets into a single dll that can be ILMerged with the preferred ServiceStack dependencies (inc. OrmLite.Sqlite) into a single cross-platform .NET exe: - -### Razor Rockstars - Embedded Edition - -To showcase its potential we've compiled the entire [Razor Rockstars](http://razor.servicestack.net/) website into a [single dll](https://github.com/ServiceStack/RazorRockstars/tree/master/src/RazorRockstars.CompiledViews) that's referenced them in the multiple use-case scenarios below: - -> Note: all demo apps are unsigned so will require ignoring security warnings to run. - -### As a Single Self-Hosted .exe - -The examples below merges Razor Rockstars and ServiceStack into a Single, cross-platform, self-hosting Console App, that opens up Razor Rockstars homepage in the users default web browser when launched: - -> [RazorRockstars.exe](https://github.com/ServiceStack/RazorRockstars/raw/master/build/RazorRockstars.exe) - Self-Host running in a Console App - -> [WindowlessRockstars.exe](https://github.com/ServiceStack/RazorRockstars/raw/master/build/WindowlessRockstars.exe) - Headless Self-Hosted Console App running in the background - -[![SelfHost](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/self-host.png)](https://github.com/ServiceStack/RazorRockstars/raw/master/build/RazorRockstars.exe) - -> The total size for the entire uncompressed **RazorRockstars.exe** ServiceStack website comes down to just **4.8MB** (lighter than the 5MB footprint of EntityFramework.dll) that includes **1.5MB** for RazorRockstars html/img/js/css website assets and **630kb** for native Windows sqlite3.dll. - -### Running inside Windows and OSX Native Desktop Apps - -You can also achieve a [PhoneGap-like experience](http://phonegap.com/) by hosting ServiceStack inside native .NET Desktop App shells for OSX and Windows: - -> [RazorRockstars.MacHost.app](https://github.com/ServiceStack/RazorRockstars/raw/master/build/RazorRockstars.MacHost.app.zip) - Running inside a Desktop Cocoa OSX app using [Xamarin.Mac](https://xamarin.com/mac) - -[![OSX Cocoa App](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/osx-host.png)](https://github.com/ServiceStack/RazorRockstars/raw/master/build/RazorRockstars.MacHost.app.zip) - -> [WpfHost.zip](https://github.com/ServiceStack/RazorRockstars/raw/master/build/WpfHost.zip) - Running inside a WPF Desktop app - -[![WPF App](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/wpf-host.png)](https://github.com/ServiceStack/RazorRockstars/raw/master/build/WpfHost.zip) - -Surprisingly .NET Desktop apps built with [Xamarin.Mac on OSX](https://xamarin.com/mac) using Cocoa's WebKit-based WebView widget provides a superior experience over WPF's built-in WebBrowser widget which renders in an old behind-the-times version of IE. To improve the experience on Windows we're exploring better experiences on Windows by researching options around the [Chromium Embedded Framework](https://code.google.com/p/chromiumembedded/) and the existing managed .NET wrappers: [CefGlue](http://xilium.bitbucket.org/cefglue/) and [CefSharp](https://github.com/cefsharp/CefSharp). - -**Xamarin.Mac** can deliver an even better end-user experience by bundling the Mono runtime with the app avoiding the need for users to have Mono runtime installed. Incidentally this is the same approach used to deploy .NET OSX apps to the [Mac AppStore](http://www.apple.com/osx/apps/app-store.html). - -### Standard Web Hosts - -As the only differences when using the embedded .dll is that it embeds all img/js/css/etc assets as embedded resources and makes use of compiled razor views, it can also be used in standard web hosts configurations which are effectively just lightweight wrappers containing the App configuration and references to external dependencies: - - - [CompiledViews in SelfHost](https://github.com/ServiceStack/RazorRockstars/tree/master/src/RazorRockstars.CompiledViews.SelfHost) - - [CompiledViews in ASP.NET Web Host](https://github.com/ServiceStack/RazorRockstars/tree/master/src/RazorRockstars.CompiledViews.WebHost) - -Benefits of Web Hosts referencing embedded dlls include easier updates by being able to update a websites core functionality by copying over a single **.dll** as well as improved performance for Razor views by eliminating Razor compile times. - -### ILMerging - -Creating the single **RazorRockstars.exe** is simply a matter of [ILMerging all the self-host project dlls](https://github.com/ServiceStack/RazorRockstars/blob/master/build/ilmerge.bat) into a single executable. - -There are only a couple of issues that need to be addressed when running in a single ILMerged .exe: - -Assembly names are merged together so all registration of assemblies in `Config.EmbeddedResourceSources` end up referencing the same assembly which results in only serving embedded resources in the host assembly namespace. To workaround this behavior we've added a more specific way to reference assemblies in `Config.EmbeddedResourceBaseTypes`, e.g: - - ```csharp - SetConfig(new HostConfig { - DebugMode = true, - EmbeddedResourceBaseTypes = { GetType(), typeof(BaseTypeMarker) }, -}); -``` - -Where `BaseTypeMarker` is just a dummy class that sits on the base namespace of the class library that's used to preserve the Assembly namespace. - -The other limitation is not being able to merge unmanaged .dll's, which is what's needed for RazorRockstars as it makes use of the native `sqlite3.dll`. An easy workaround for this is to make `sqlite3.dll` an embedded resource then simply write it out to the current directory where OrmLite.Sqlite can find it when it first makes an sqlite connection, e.g: - - ```csharp -public static void ExportWindowsSqliteDll() -{ - if (Env.IsMono) - return; //Uses system sqlite3.so or sqlite3.dylib on Linux/OSX - - var resPath = "{0}.sqlite3.dll".Fmt(typeof(AppHost).Namespace); - - var resInfo = typeof(AppHost).Assembly.GetManifestResourceInfo(resPath); - if (resInfo == null) - throw new Exception("Couldn't load sqlite3.dll"); - - var dllBytes = typeof(AppHost).Assembly.GetManifestResourceStream(resPath).ReadFully(); - var dirPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - var filePath = Path.Combine(dirPath, "sqlite3.dll"); - - File.WriteAllBytes(filePath, dllBytes); -} -``` - -This isn't required for Mono as it's able to make use of the preinstalled version of sqlite on OSX and Linux platforms. - -### Compiled Razor Views - -Support for Compiled Razor Views has landed in ServiceStack thanks to the efforts of [Carl Healy](https://github.com/Tyst). - -The primary benefits of compiled views is improved performance by eliminating compile times of Razor views. They also provide static compilation benefits by highlighting compile errors during development and also save you from deploying multiple `*.cshtml` files with your app since they all end up pre-compiled in your Assembly. - -Enabling compiled views is fairly transparent where you only need to install the new [Razor.BuildTask NuGet Package](https://www.nuget.org/packages/ServiceStack.Razor.BuildTask/) to the project containing your `.cshtml` Razor Views you want to compile: - - PM> Install-Package ServiceStack.Razor.BuildTask - -This doesn't add any additional dlls to your project, instead it just sets the **BuildAction** to all `*.cshtml` pages to `Content` and adds an MSBuild task to your project file to pre-compile razor views on every build. - -Then to register assemblies containing compiled razor views with Razor Format you just need to add it to `RazorFormat.LoadFromAssemblies`, e.g: - -```csharp -Plugins.Add(new RazorFormat { - LoadFromAssemblies = { typeof(RockstarsService).Assembly } -}); -``` - -The Compiled Views support continues to keep a great development experience in [DebugMode](https://github.com/ServiceStack/ServiceStack/wiki/Debugging#debugmode) where all Razor Views are initially loaded from the Assembly but then continues to monitor the file system for modified views, automatically compiling and loading them on the fly. - -## [Postman Support](http://www.getpostman.com/) - -We've added great support for the very popular [Postman Rest Client](http://www.getpostman.com/) in this release which is easily enabled by just registering the plugins below: - -```csharp -Plugins.Add(new PostmanFeature()); -Plugins.Add(new CorsFeature()); -``` - -> As it makes cross-site requests, Postman also requires CORS support. - -Once enabled, a link with appear in your metadata page: - -![Postman Metadata link](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/postman-metadata.png) - -Which by default is a link to `/postman` route that returns a JSON postman collection that can be imported into postman by clicking on **import collections** icon at the top: - -![Postman Screenshot](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/postman.png) - -Once imported it will populate a list of available routes which you can select and easily call from the Postman UI. Just like the [Swagger Support](https://github.com/ServiceStack/ServiceStack/wiki/Swagger-API) the list of operations returned respects the [Restriction Attributes](https://github.com/ServiceStack/ServiceStack/wiki/Restricting-Services) and only shows the operations each user is allowed to see. - -The above screenshot shows how to call the `SearchRockstars` Route `/rockstars/{Id}` which returns the rockstar with the matching id. - -The screenshot above also illustrates some of the customization that's available with the [Email Contacts](https://github.com/ServiceStack/EmailContacts/) metadata imported with the default settings and the Razor Rockstars metadata imported with a customized label: - - /postman?label=type,+,route - -The `label` param accepts a collection of string tokens that controls how the label is formatted.The `type` and `route` are special tokens that get replaced by the **Request DTO name** and **Route** respectively. Everything else are just added string literals including the `+` character which is just a url-encoded version of ` ` space character. - -Here are some examples using the example definition below: - -```csharp -[Route("/contacts/{Id}")] -public class GetContact { ... } -``` - -
      - - - - - - - - - - - - - - - - -
      /postman?label=typeGetContact
      /postman?label=route/contacts/{Id}
      /postman?label=type:englishGet contact
      /postman?label=type:english,+(,route,)Get contact (/contacts/{Id})
      - -The default label format can also be configured when registering the Postman plugin, e.g: - -```csharp -Plugins.Add(new PostmanFeature { - DefaultLabelFmt = new List { "type:english", " ", "route" } -}); -``` - -### Support for authenticated requests - -We've also made it easy to call authentication-only services with the `/postman?exportSession=true` parameter which will redirect to a url that captures your session cookies into a deep-linkable url like `/postman?ssopt=temp&ssid={key}&sspid={key}` that can be copied into Postman. - -This lets you replace your session cookies with the session ids on the url, effectively allowing you to take over someone elses session, in this case telling Postman to make requests on your behalf using your authenticated session cookies. - -As this functionality is potentially dangerous it's only enabled by default in **DebugMode** but can be overridden with: - -```csharp -Plugins.Add(new PostmanFeature { - EnableSessionExport = true -}); -``` - -### Other Customizations - -Other options include hosting postman on an alternate path, adding custom HTTP Headers for each Postman request and providing friendly aliases for Request DTO Property Types that you want to appear to external users, in this case we can show `DateTime` types as `Date` in Postmans UI: - -```csharp -Plugins.Add(new PostmanFeature { - AtRestPath = "/alt-postman-link", - Headers = "X-Custom-Header: Value\nXCustom2: Value2", - FriendlyTypeNames = { {"DateTime", "Date"} }, -}); -``` - -## [Cascading layout templates](http://razor.servicestack.net/#no-ceremony) - -Support for [Cascading layout templates](http://razor.servicestack.net/#no-ceremony) for Razor ViewPages inside `/Views` were added in this release by [@Its-Tyson](https://github.com/Its-Tyson). - -This works the same intuitive way it does for external Razor Content pages where the `_Layout.cshtml` nearest to the selected View will be used by default, e.g: - - /Views/_Layout.cshtml - /Views/Public.cshtml - /Views/Admin/_Layout.cshtml - /Views/Admin/Dashboard.cshtml - -Where `/Views/Admin/Dashboard.cshtml` by default uses the `/Views/Admin/_Layout.cshtml` template. - -## Async APIs added to HTTP Utils - -The following Async versions of [HTTP Utils](https://github.com/ServiceStack/ServiceStack/wiki/Http-Utils) have been added to ServiceStack.Text by [Kyle Gobel](https://github.com/KyleGobel): - -```csharp -Task GetStringFromUrlAsync(...) -Task PostStringToUrlAsync(...) -Task PostToUrlAsync(...) -Task PostJsonToUrlAsync(...) -Task PostXmlToUrlAsync(...) -Task PutStringToUrlAsync(...) -Task PutToUrlAsync(...) -Task PutJsonToUrlAsync(...) -Task PutXmlToUrlAsync(...) -Task DeleteFromUrlAsync(...) -Task OptionsFromUrlAsync(...) -Task HeadFromUrlAsync(...) -Task SendStringToUrlAsync(...) -``` - -## Redis - -The latest [stable release of redis-server](http://download.redis.io/redis-stable/00-RELEASENOTES) includes support for the new [ZRANGEBYLEX](http://redis.io/commands/zrangebylex) sorted set operations allowing you to query a sorted set lexically. A good showcase for this is available on [autocomplete.redis.io](http://autocomplete.redis.io/) that shows a demo querying all 8 millions of unique lines of the Linux kernel source code in a fraction of a second. - -These new operations are available as a 1:1 mapping with redis-server on IRedisNativeClient: - -```csharp -public interface IRedisNativeClient -{ - ... - byte[][] ZRangeByLex(string setId, string min, string max, int? skip = null, int? take = null); - long ZLexCount(string setId, string min, string max); - long ZRemRangeByLex(string setId, string min, string max); -} -``` - -As well as under more user-friendly APIs under IRedisClient: - -```csharp -public interface IRedisClient -{ - ... - List SearchSortedSet(string setId, string start=null, string end=null, int? skip=null, int? take=null); - long SearchSortedSetCount(string setId, string start=null, string end=null); - long RemoveRangeFromSortedSetBySearch(string setId, string start=null, string end=null); -} -``` - -Just like NuGet version matchers, Redis uses `[` char to express inclusiveness and `(` char for exclusiveness. -Since the `IRedisClient` APIs defaults to inclusive searches, these two APIs are the same: - -```csharp -Redis.SearchSortedSetCount("zset", "a", "c") -Redis.SearchSortedSetCount("zset", "[a", "[c") -``` - -Alternatively you can specify one or both bounds to be exclusive by using the `(` prefix, e.g: - -```csharp -Redis.SearchSortedSetCount("zset", "a", "(c") -Redis.SearchSortedSetCount("zset", "(a", "(c") -``` - -More API examples are available in [LexTests.cs](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests/LexTests.cs). - -### Twemproxy support - -This release also includes better support for [twemproxy](https://github.com/twitter/twemproxy), working around missing server commands sent upon connection. - -## OrmLite - -New support for StringFilter allowing you apply custom filter on string values, e.g [remove trailing whitespace](http://stackoverflow.com/a/23261868/85785): - -```csharp -OrmLiteConfig.StringFilter = s => s.TrimEnd(); - -db.Insert(new Poco { Name = "Value with trailing " }); -Assert.That(db.Select().First().Name, Is.EqualTo("Value with trailing")); -``` - -Added implicit support for [escaping wildcards in typed expressions](http://stackoverflow.com/a/23435975/85785) that make use of LIKE, namely `StartsWith`, `EndsWith` and `Contains`, e.g: - -```csharp -db.Insert(new Poco { Name = "ab" }); -db.Insert(new Poco { Name = "a%" }); -db.Insert(new Poco { Name = "a%b" }); - -db.Count(q => q.Name.StartsWith("a_")); //0 -db.Count(q => q.Name.StartsWith("a%")); //2 -``` - -OrmLite also underwent some internal refactoring to remove duplicate code and re-use existing code-paths. - -### Other Features - - - Allow overriding of `HttpListenerBase.CreateRequest()` for controlling creation of Self-Hosting requests allowing you to force a [Character encoding to override the built-in heuristics](http://stackoverflow.com/a/23381383/85785) for detecting non UTF-8 character encodings - - Support for retrieving untyped `base.UserSession` when inheriting from an untyped MVC `ServiceStackController` - - Added `@Html.RenderErrorIfAny()` to render a pretty bootstrap-styled exception response in a razor view - - The generated WSDL output now replaces all occurances of `http://schemas.servicestack.net/types` with `Config.WsdlServiceNamespace` - - Initialize the CompressedResult Status code with the current HTTP ResponseStatus code - - Plugins implementing `IPreInitPlugin` are now configured immediately after `AppHost.Configure()` - - HttpListeners now unwrap async Aggregate exceptions containing only a Single Exception for better error reporting - - HttpListeners now shares the same behavior as IIS for [redirecting requests for directories without a trailing slash](https://github.com/ServiceStack/ServiceStack/commit/a0a2857721656c7161fcd83eb07609ae4239ea2a) - - [Debug Request Info](https://github.com/ServiceStack/ServiceStack/wiki/Debugging#request-info) now shows file listing of the configured VirtualPathProvider - - Resource Virtual Directories are no longer case-sensitive - - Added new `Config.ExcludeAutoRegisteringServiceTypes` option to exclude services from being implicitly auto registered from assembly scanning. All built-in services in ServiceStack.dll now excluded by default which removes unintentional registration of services from ILMerging. - -# New HTTP Benchmarks example project - -[![HTTP Benchmarks](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/benchmarks-admin-ui.png)](https://httpbenchmarks.servicestack.net/) - -Following the release of the [Email Contacts](https://github.com/ServiceStack/EmailContacts/) solution, a new documented ServiceStack example project allowing you to uploaded Apache HTTP Benchmarks to visualize and analyze their results has been released at: [github.com/ServiceStack/HttpBenchmarks](https://github.com/ServiceStack/HttpBenchmarks) and is hosted at [httpbenchmarks.servicestack.net](https://httpbenchmarks.servicestack.net/). - -### Example Results - - - [Performance of different RDBMS in an ASP.NET Host](https://httpbenchmarks.servicestack.net/databases-in-asp-net) - - [Performance of different ServiceStack Hosts](https://httpbenchmarks.servicestack.net/servicestack-hosts) - -The documentation includes a development guide that walks through the projects different features: - - - Integration with `Glimpse` with support for `DotNetOpenAuth` - - Allow authentication with Twitter, Facebook, Google and LinkedIn OAuth providers - - Enables registration of new user accounts - - Use of `[FallbackRoute]` attribute to allow users to create top-level routes (e.g. twitter.com/name) - - Explains why you want to aim for minimal JS dependencies - - Introduction of **Really Simple MV Pattern** using plain JavaScript - - Integration with multi-file Uploader `FineUploader` - - Processes multiple file uploads including files in **.zip** packages using `DotNetZip` - - Integration with `Highcharts.js` - - Hosting differences of ASP.NET with AWS - - Deploying to AWS and creating customized deployment packages with MSDeploy - - Configuring SSL - - Forcing SSL Redirects - -The repository also includes benchmark scripts and host projects of [all ServiceStack HTTP Hosts](https://github.com/ServiceStack/HttpBenchmarks/tree/master/servers -), which all support runtime configuration of different RDBMS's: - -# v4.0.18 Release Notes - -## New, much faster Self-Host! - -Prior to this release ServiceStack had 2 self-hosting options with different [Concurrency Models](https://github.com/ServiceStack/ServiceStack/wiki/Concurrency-model): - -- `AppHostHttpListenerBase` - Executes requests on the IO callback thread -- `AppHostHttpListenerPoolBase` - Executes requests on .NET's built-in ThreadPool - -Where in typical scenarios (i.e. CPU intensive or blocking IO), executing on .NET's Thread Pool provides better performance. - -This [Self-hosting performance analysis](http://en.rdebug.com/2013/05/06/servicestack-selfhosted-performance-boost/) from the ServiceStack community shows we're able to achieve even better performance by utilizing the excellent [Smart Thread Pool](http://www.codeproject.com/Articles/7933/Smart-Thread-Pool) instead, which is now available in the `AppHostHttpListenerSmartPoolBase` base class. - -The new Smart Pool self-host routinely outperforms all other self hosting options, and does especially well in heavy IO scenarios as seen in the benchmarks below: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Self HostASP.NET/IIS ExpressHttpListener PoolHttpListener
      Database updates1x1.9x2x4.1x
      Single database query1x1.2x1.5x2.6x
      Multiple database queries1x1.2x1.4x2.6x
      Plaintext1x2.3x2.4x1.6x
      Fortunes Razor View1x1.2x1.5x1.8x
      JSON serialization1x1.2x1.4x1x
      - -### Using different Self Host options - -You can easily switch between the different self-hosting options by simply changing your AppHost's base class, e.g: - -```csharp -public class AppHost : AppHostHttpListenerBase { ... } -public class AppHost : AppHostHttpListenerPoolBase { ... } -public class AppHost : AppHostHttpListenerSmartPoolBase { ... } -``` - -Both the HttpListener Pool and SmartPool hosts have configurable pool sizes that can be tweaked to perform better under different scenarios. - -### Optimal Self Hosted option - -As the number of self-hosts grow, we've added a new `AppSelfHostBase` base class that represents an alias for the highest performing self-hosting option with an optimal configuration that we'll continue to tune for performance against typical scenarios. Unless you've identified specific configurations that performs better for your use-case, the recommendation is for new self-hosts to inherit this configuration: - -```csharp -public class AppHost : AppSelfHostBase { ... } -``` - -## OrmLite - -OrmLite received a lot more attention this release with a number of value-added additions: - -### Improved Oracle RDBMS provider - -The OrmLite Oracle Provider has been significantly improved thanks to [Bruce Cowen](https://github.com/BruceCowan-AI) efforts who's brought the quality in-line with other RDBMS providers which now passes OrmLite's test suite. As part of this change, the Oracle Provider now depends on [Oracle's Data Provider for .NET](http://www.oracle.com/technetwork/topics/dotnet/index-085163.html) and can be installed with: - - PM> Install-Package ServiceStack.OrmLite.Oracle - PM> Install-Package ServiceStack.OrmLite.Oracle.Signed - -More notes about the Oracle provider are maintained in the [OrmLite Release Notes](https://github.com/ServiceStack/ServiceStack.OrmLite/#oracle-provider-notes). - -### Improved Typed SqlExpressions - -The existing `db.SqlExpression()` API has a more readable alias in: - -```csharp -db.From(); -``` - -Which now supports an optional SQL **FROM** fragment that can be used to specify table joins, e.g: - - var results = db.Select(db.From("Person INNER JOIN Band ON Person.Id = Band.PersonId")); - -#### New ISqlExpression API - -OrmLite API's have overloads to execute any SQL builders that implement the simple `ISqlExpression` API, i.e: - -```csharp -public interface ISqlExpression -{ - string ToSelectStatement(); -} -``` - -This allows for more readable code when using a decoupled Sql Builder, e.g: - -```csharp -int over40s = db.Scalar(db.From().Select(Sql.Count("*")).Where(q => q.Age > 40)); - -List lastNames = db.Column(db.From().Select(x => x.LastName).Where(q => q.Age == 27)); - -HashSet uniqueAges = db.ColumnDistinct(db.From().Select(x => x.Age).Where(q => q.Age < 50)); - -Dictionary map = db.Dictionary(db.From().Select(x => new {x.Id, x.LastName})); -``` - -#### Partial Selects - -This also improves the APIs for partial SELECT queries, which originally required the use of custom SQL: - -```csharp -var partialColumns = db.SelectFmt(typeof(Shipper), "ShipperTypeId = {0}", 2); -``` - -But can now be expressed in any of the more typed examples below: - -```csharp -var partialColumns = db.Select(db.From().Where(q => q.ShipperTypeId == 2)); -``` - -Or partially populating the same POCO with only the columns specified: - -```csharp -var partialColumns = db.Select(q => q.Select(x => new { x.Phone, x.CompanyName }) - .Where(x => x.ShipperTypeId == 2)); - -var partialColumns = db.Select(q => q.Select("Phone, CompanyName") - .Where(x => x.ShipperTypeId == 2)); -``` - -#### Nullable Limit APIs - -The Limit API's now accept `int?` making it easier to apply paging in your ServiceStack services, e.g: - -```csharp -public Request -{ - public int? Skip { get; set; } - public int? Take { get; set; } -} - -public List
      Any(Request request) -{ - return Db.Select(db.From
      .Limit(request.Skip, request.Take)); -} -``` - -Which will only filter the results for the values provided. Aliases for `Skip()` and `Take()` are also available if LINQ naming is preferred. - -#### New AliasNamingStrategy - -A new alias naming strategy was added (in addition to `[Alias]` attribute) that lets you specify a dictionary of Table and Column aliases OrmLite should used instead, e.g: - -```csharp -OrmLiteConfig.DialectProvider.NamingStrategy = new AliasNamingStrategy { - TableAliases = { { "MyTable", "TableAlias" } }, - ColumnAliases = { { "MyField", "ColumnAlias" } }, -}; -``` - -Which OrmLite will use instead, e.g when creating a table: - -```csharp -db.CreateTable(); -``` - -Aliases can also be referenced when creating custom SQL using the `SqlTable()` and `SqlColumn()` extension methods, e.g: - -```csharp -var result = db.SqlList( - "SELECT * FROM {0} WHERE {1} = {2}".Fmt( - "MyTable".SqlTable(), - "MyField".SqlColumn(), "foo".SqlValue())); -``` - -#### New Exists APIs - -Nicer if you just need to check for existence, instead of retrieving a full result-set e.g: - -```csharp -bool hasUnder50s = db.Exists(x => x.Age < 50); -bool hasUnder50s = db.Exists(db.From().Where(x => x.Age < 50)); -``` - -## Redis - -### New Scan APIs Added - -Redis v2.8 introduced a beautiful new [SCAN](http://redis.io/commands/scan) operation that provides an optimal strategy for traversing a redis instance entire keyset in managable-size chunks utilizing only a client-side cursor and without introducing any server state. It's a higher performance alternative and should be used instead of [KEYS](http://redis.io/commands/keys) in application code. SCAN and its related operations for traversing members of Sets, Sorted Sets and Hashes are now available in the Redis Client in the following API's: - -```csharp -public interface IRedisClient -{ - ... - IEnumerable ScanAllKeys(string pattern = null, int pageSize = 1000); - IEnumerable ScanAllSetItems(string setId, string pattern = null, int pageSize = 1000); - IEnumerable> ScanAllSortedSetItems(string setId, string pattern = null, int pageSize = 1000); - IEnumerable> ScanAllHashEntries(string hashId, string pattern = null, int pageSize = 1000); -} - -//Low-level API -public interface IRedisNativeClient -{ - ... - ScanResult Scan(ulong cursor, int count = 10, string match = null); - ScanResult SScan(string setId, ulong cursor, int count = 10, string match = null); - ScanResult ZScan(string setId, ulong cursor, int count = 10, string match = null); - ScanResult HScan(string hashId, ulong cursor, int count = 10, string match = null); -} -``` - -The `IRedisClient` provides a higher-level API that abstracts away the client cursor to expose a lazy Enumerable sequence to provide an optimal way to stream scanned results that integrates nicely with LINQ, e.g: - -```csharp -var scanUsers = Redis.ScanAllKeys("urn:User:*"); -var sampleUsers = scanUsers.Take(10000).ToList(); //Stop after retrieving 10000 user keys -``` - -### New HyperLog API - -The development branch of Redis server (available when v3.0 is released) includes an ingenious algorithm to approximate the unique elements in a set with maximum space and time efficiency. For details about how it works see Redis's creator Salvatore's blog who [explains it in great detail](http://antirez.com/news/75). Essentially it lets you maintain an efficient way to count and merge unique elements in a set without having to store its elements. -A Simple example of it in action: - -```csharp -redis.AddToHyperLog("set1", "a", "b", "c"); -redis.AddToHyperLog("set1", "c", "d"); -var count = redis.CountHyperLog("set1"); //4 - -redis.AddToHyperLog("set2", "c", "d", "e", "f"); - -redis.MergeHyperLogs("mergedset", "set1", "set2"); - -var mergeCount = redis.CountHyperLog("mergedset"); //6 -``` - -## HTTP and MQ Service Clients - -### Substitutable OneWay MQ and HTTP Service Clients - -Service Clients and MQ Clients have become a lot more interoperable where all MQ Clients now implement the Service Clients `IOneWayClient` API which enables writing code that works with both HTTP and MQ Clients: - -```csharp -IOneWayClient client = GetClient(); -client.SendOneWay(new RequestDto { ... }); -``` - -Likewise the HTTP Service Clients implement the Messaging API `IMessageProducer`: - -```csharp -void Publish(T requestDto); -void Publish(IMessage message); -``` - -When publishing a `IMessage` the message metadata are sent as HTTP Headers with an `X-` prefix. - -### UploadProgress added on Service Clients - -Which works similar to [OnDownloadProgress](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/AsyncProgressTests.cs) where you can specify a callback to provide UX Progress updates, e.g: - -```csharp -client.OnUploadProgress = (bytesWritten, total) => "Written {0}/{1} bytes...".Print(bytesWritten, total); - -client.PostFileWithRequest(url, new FileInfo(path), new Upload { CreatedBy = "Me" }); -``` - -## Razor Support - -Our support for [No Ceremony Razor pages](https://github.com/ServiceStack/EmailContacts/#the-no-ceremony-option---dynamic-pages-without-controllers) has been very well received which has all but alleviated the need of requiring services / controllers for dynamic html pages. One of the areas where a Service may be required is for execution any custom request filters, which we've now added support for by letting you choose to execute all request filters for a specific Request with: - -```csharp -@{ - ApplyRequestFilters(new RequestDto()); -} -``` - -This will execute all the Request Filters applied to the specified Request DTO. Any one of the filters ends the request (e.g. with a redirect) and the rest of the Razor page will stop execution. - -Likewise it's possible to redirect from within Razor with: - -```csharp -@{ - if (!IsAuthenticated) { - Response.RedirectToUrl("/login"); - throw new StopExecutionException(); - } -} -``` -An alternative to `StopExecutionException` is to have an explicit `return;`, the difference being that it will continue to execute the remainder of the page, although neither approach will emit any Razor output to the response. - -As redirecting non-authenticated users is a common use-case it's also available as a one-liner: - -```csharp -@{ - RedirectIfNotAuthenticated(); -} -``` - -Which if no url is specified it will redirect to the path configured on `AuthFeature.HtmlRedirect`. - -### ss-utils.js - -A few enhancements were added to ServiceStack's **/js/ss-utils.js** is ServiceStack's built-in JS library, first demonstrated in [Email Contacts solution](https://github.com/ServiceStack/EmailContacts/#servicestack-javascript-utils---jsss-utilsjs): - -Declarative event handlers can send multiple arguments: - -```html -
        -
      • Foo
      • -
      • Bar
      • -
      -``` - -```javascript -$(document).bindHandlers({ - single: function(){ - var li = this; - }, - multiple: function(arg1, arg2) { - var li = this; - } -}); -``` - -Trigger client-side validation errors with `setFieldError()`: - -```javascript -$("form").bindForm({ - validate: function(){ - var params = $(this).serializeMap(); - if (params.Password != params.Confirm){ - $(this).setFieldError('Password', 'Passwords to not match'); - return false; - } - } -}); -``` - -Model binding now also populates `data-href` and `data-src` attributes e.g: - -```html - -``` - -```javascript -$("form").applyValues({ FieldName: imgUrl }); -``` -## Other Changes - -### Restriction attributes allowed on Services - -Restriction attributes can be added on Service classes in addition to Request DTOs (which still take precedence). - -```csharp -[Restrict(LocalhostOnly = true)] -public class LocalHostOnlyServices : Service { ... } -``` - -## AppSettings - -### New OrmLiteAppSettings - -Added new read/write AppSettings config option utilizing OrmLite as the back-end. -This now lets you maintain your applications configuration in any [RDBMS back-end OrmLite supports](https://github.com/ServiceStack/ServiceStack.OrmLite/#download). It basically works like a mini Key/Value database in which can store any serializable value against any key which is maintained into the simple Id/Value `ConfigSettings` table. - -#### Usage - -Registration just uses an OrmLite DB Factory, e.g: - -```csharp -container.Register(c => new OrmLiteAppSettings(c.Resolve())); -var appSettings = container.Resolve(); -appSettings.InitSchema(); //Create the ConfigSettings table if it doesn't exist -``` - -It then can be accessed like any [AppSetting APIs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Common.Tests/Configuration/AppSettingsTests.cs): - -```csharp -//Read the `MyConfig` POCO stored at `config` otherwise use default value if it doesn't exist -MyConfig config = appSettings.Get("config", new MyConfig { Key = "DefaultValue" }); -``` - -It also supports writing config values in addition to the AppSettings read-only API's, e.g: - -```csharp -var latestStats = appSettings.GetOrCreate("stats", () => statsProvider.GetLatest()); -``` - -### Extract key / value settings from text file - -The new ParseKeyValueText extension method lets you extract key / value data from text, e.g: - -```csharp -var configText = @" -StringKey string value -IntKey 42 -ListKey A,B,C,D,E -DictionaryKey A:1,B:2,C:3,D:4,E:5 -PocoKey {Foo:Bar,Key:Value}"; - -Dictionary configMap = configText.ParseKeyValueText(delimiter:" "); -``` - -When combined with the existing `DictionarySettings`, enables a rich, simple and clean alternative to .NET's App.config config section for reading structured configuration into clean data structures, e.g: - -```csharp -IAppSettings appSettings = new DictionarySettings(configMap); - -string value = appSettings.Get("StringKey"); - -int value = appSettings.Get("IntKey", defaultValue:1); - -List values = appSettings.GetList("ListKey"); - -Dictionary valuesMap = appSettings.GetList("DictionaryKey"); - -MyConfig config = appSettings.Get("PocoKey", new MyConfig { Key = "DefaultValue"}); -``` - -As we expect this to be a popular combination we've combined them into a single class that accepts a filePath, providing a simple alternative to custom Web.config configurations: - -```csharp -var appSettings = new TextFileSettings("~/app.settings".MapHostAbsolutePath()); -``` - -### PerfUtils - -We've included the [C# Benchmark Utils](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/PerfUtils.cs) previously used in [Sudoku Benchmarks](https://github.com/dartist/sudoku_solver#benchmarks) originally inspired from [Dart's benchmark_harness](https://github.com/dart-lang/benchmark_harness). Unlike other benchmark utils, it runs for a specified period of time (2000ms by default) then returns the avg iteration time in microseconds. Here's an example usage comparing performance of maintaining a unique int collection between HashSet vs List: - -```csharp -var rand = new Random(); -var set = new HashSet(); -var avgMicroSecs = PerfUtils.Measure( - () => set.Add(rand.Next(0, 1000)), runForMs:2000); - -"HashSet: {0}us".Print(avgMicroSecs); - -var list = new List(); -avgMicroSecs = PerfUtils.Measure(() => { - int i = rand.Next(0, 1000); - if (!list.Contains(i)) - list.Add(i); - }, runForMs: 2000); - -"List: {0}us".Print(avgMicroSecs); -``` - -### Minor Changes - -- Numeric type mismatches between POCOs used in OrmLite and underlying RDBMS Tables are transparently coerced -- `Vary: Accept` is included in Global HTTP Headers to resolve browsers caching different Content-Type for the same url -- Razor configuration removes references to a specific version of ASP.NET Web Pages and adds `System` to default namespaces -- Swagger API emits an ApiVersion, configurable with `Config.ApiVersion` that defaults to "1.0" -- Partials now render inside user-defined Razor sections -- Added `email.ToGravatarUrl()` extension method to retrieve avatar url from an email -- Replaced self-hosts use of ThreadStatics with CallContext to preserve Request scope in async requests -- Avoid runtime razor exceptions in Mono by not registering duplicate assemblies (i.e. from GAC) in RazorHost -- AppHostHttpListenerPoolBase self-host has a default pool size of `16 x Environment.ProcessorCount` -- ServiceStack's `IAppHost.CustomErrorHttpHandlers` can now override built-in HTTP Error handlers and fallback to generic error responses - -### New Signed Projects - -- [ServiceStack.ProtoBuf.Signed](https://www.nuget.org/packages/ServiceStack.ProtoBuf.Signed) - -### Breaking Changes - -- Moved `Config.GlobalHtmlErrorHttpHandler` to `IAppHost.GlobalHtmlErrorHttpHandler` - - -# v4.0.15 Release Notes - -### Individual Products now available - -In this release we've added the most requested "non-technical feature" by creating new licenses for [individual ServiceStack products](https://servicestack.net/#products) which provide -much better value when only using one of ServiceStack's stand-alone libraries on their own. - -New products available: - - - [servicestack.net/text](https://servicestack.net/text) - - [servicestack.net/redis](https://servicestack.net/redis) - - [servicestack.net/ormlite](https://servicestack.net/ormlite) - -> Both OrmLite and Redis includes an implicit license for ServiceStack.Text - -### ServiceStack - - - Upgraded ServiceStack's external dependencies to use latest version on NuGet - - Modified [ServiceStack.RabbitMq](http://www.nuget.org/packages/ServiceStack.RabbitMq) to only depend on **ServiceStack** instead of **ServiceStack.Server** - - Added optional `fieldName` property to ServiceClient [PostFileWithRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/IRestClient.cs#L52-L55) - - Changed exceptions in FileSystem scanning to be logged as warnings, fixes issues with NTFS symbolic links - - Pass through Thread CurrentCulture when executing a sync request in a new Task - - Added Evaluator.NamespaceAssemblies to specify alternate default namespace for Assemblies - - Changed to use OrdinalIgnoreCase instead of InvariantCultureIgnoreCase when possible - -### OrmLite - -#### OrmLite's core Exec functions are now overridable as a Filter - -Continuing in efforts to make OrmLite more introspectable and configurable, OrmLite's core Exec functions -[have been re-factored out into a substitutable Exec Filter](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/fa55404200f4a319eae3a298b648462dadafce5e). - -This now makes it possible to inject a custom managed exec function where you can inject your own behavior, tracing, profiling, etc. - -It comes in useful for situations when you want to use SqlServer in production but use an `in-memory` Sqlite database in tests and you want to emulate any missing SQL Server Stored Procedures in code: - -```csharp -public class MockStoredProcExecFilter : OrmLiteExecFilter -{ - public override T Exec(IDbConnection dbConn, Func filter) - { - try - { - return base.Exec(dbConn, filter); - } - catch (Exception ex) - { - if (dbConn.GetLastSql() == "exec sp_name @firstName, @age") - return (T)(object)new Person { FirstName = "Mocked" }; - throw; - } - } -} - -OrmLiteConfig.ExecFilter = new MockStoredProcExecFilter(); - -using (var db = OpenDbConnection()) -{ - var person = db.SqlScalar("exec sp_name @firstName, @age", - new { firstName = "aName", age = 1 }); - - person.FirstName.Print(); //Mocked -} -``` -Or if you want to do things like executing each operation multiple times, e.g: - -```csharp -public class ReplayOrmLiteExecFilter : OrmLiteExecFilter -{ - public int ReplayTimes { get; set; } - - public override T Exec(IDbConnection dbConn, Func filter) - { - var holdProvider = OrmLiteConfig.DialectProvider; - var dbCmd = CreateCommand(dbConn); - try - { - var ret = default(T); - for (var i = 0; i < ReplayTimes; i++) - { - ret = filter(dbCmd); - } - return ret; - } - finally - { - DisposeCommand(dbCmd); - OrmLiteConfig.DialectProvider = holdProvider; - } - } -} - -OrmLiteConfig.ExecFilter = new ReplayOrmLiteExecFilter { ReplayTimes = 3 }; - -using (var db = OpenDbConnection()) -{ - db.DropAndCreateTable(); - db.Insert(new PocoTable { Name = "Multiplicity" }); - - var rowsInserted = db.Count(q => q.Name == "Multiplicity"); //3 -} -``` - -#### Other improvements - - - Added [SqlVerifyFragment string extension](https://github.com/ServiceStack/ServiceStack.OrmLite/commit/7f0711aa3368087037d8b7b84cf9f70f1ea2b191) to verify sql fragments where free-text is allowed in SqlExpression APIs - - Change MySql to create TimeSpan's column as INT to store ticks - -### Redis - - - Add new Increment by double and long methods to Redis Client - -### Text - - - Added [T.PopulateFromPropertiesWithoutAttribute](https://github.com/ServiceStack/ServiceStack.Text/commit/9bd0cc35c0a4e3ddcb7e6b6b88e760f45496145b) Auto Mapping method - -### New Signed NuGet Packages - - - [ServiceStack.OrmLite.Sqlite.Windows.Signed](http://www.nuget.org/packages/ServiceStack.OrmLite.Sqlite.Windows.Signed) - -# v4.0.12 Release Notes - -## New [Email Contact Services](https://github.com/ServiceStack/EmailContacts/) - -A new ServiceStack guidance is available detailing the recommended setup and physical layout structure of typical medium-sized ServiceStack projects. -It includes the complete documentation going through how to create the solution from scratch, and explains all the ServiceStack hidden features it makes use of along the way. - -[![EmailContacts Screenshot](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/email-contacts.png)](https://github.com/ServiceStack/EmailContacts/) - -[EmailContacts](https://github.com/ServiceStack/EmailContacts/) is a Single Page App built using just ServiceStack, -jQuery and Bootstrap that showcases some of ServiceStack's built-in features, useful in the reducing the effort for -developing medium-sized Web Applications. - -The purpose of EmailContacts is to manage contacts (in [any RDBMS](https://github.com/ServiceStack/ServiceStack.OrmLite/#download)), -provide a form to be able to send them messages and maintain a rolling history of any emails sent. -The application also provides an option to have emails instead sent and processed via [Rabbit MQ](https://github.com/ServiceStack/ServiceStack/wiki/Rabbit-MQ). - -#### Functional Single Page App in under 130 Lines of HTML and 70 Lines JS - -The entire EmailContacts UI is maintained in a single -[default.cshtml](https://github.com/ServiceStack/EmailContacts/blob/master/src/EmailContacts/default.cshtml) -requiring just 70 lines of JavaScript to render the dynamic UI, -bind server validation errors and provide real-time UX feedback. -The Application also follows an API-First development style where the Ajax UI calls only published APIs allowing -all services to be immediately available, naturally, via an end-to-end typed API to Mobile and Desktop .NET clients. - -### Example Projects - -During this release all Example projects, Demos, Starter Templates, etc in the -[ServiceStack.Example](https://github.com/ServiceStack/ServiceStack.Examples) and -[ServiceStack.UseCases](https://github.com/ServiceStack/ServiceStack.UseCases/) -master repositories were upgraded to ServiceStack v4. A new [ServiceStack + MVC5 project](https://github.com/ServiceStack/ServiceStack.UseCases/tree/master/Mvc5) -was also added to UseCases, it just follows the instructions at [MVC Integration](https://github.com/ServiceStack/ServiceStack/wiki/Mvc-integration) wiki, but starts with an empty MVC5 project. - -### Added new OrmLiteCacheClient - -A new `OrmLiteCacheClient` [Caching Provider](https://github.com/ServiceStack/ServiceStack/wiki/Caching) -was added to the **ServiceStack.Server** NuGet pacakge. -This provides a lot of utility by supporting -[OrmLite's RDBMS providers](https://github.com/ServiceStack/ServiceStack.OrmLite/#download) -allowing utilization of existing RDBMS's as a distributed cache, potentially saving an infrastructure dependency. - -Registration is simply: - -```csharp -//Register OrmLite Db Factory if not already -container.Register(c => - new OrmLiteConnectionFactory(connString, SqlServerDialect.Provider)); - -container.RegisterAs(); - -//Create 'CacheEntry' RDBMS table if it doesn't exist already -container.Resolve().InitSchema(); -``` - -### Service Clients - - - Added `CaptureSynchronizationContext` option to get Async Service Clients to execute responses on the same SynchronizationContext as their call-site - - Added `UserAgent` option, now defaults with the ServiceStack .NET client version - -### Minor features - - - Allow unrestricted access for Redis MQ and Rabbit MQ clients within free-quotas - - SessionIds are no longer created with Url Unfriendly chars `+`, `/` - - Add typed `ToOneWayUrl()` and `ToReplyUrl()` extension method for generating predefined urls - - Add Test showing how to use `ExecAllAndWait` extension method to [easily run synch operations in parallel](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Common.Tests/ActionExecTests.cs) - - Added configurable BufferSize in StaticFileHandler - - All CacheClients can now store AuthUserSessions when `JsConfig.ExcludeTypeInfo=true` - - Allow RegistrationService to be used for PUT requests to updates User Registration info - - Elmah Logger now takes in a `HttpApplication` so it can use `ErrorSignal.Get(application).Raise()` allowing modules such as ErrorMail and ErrorPost (ElmahR) to be notified - -## OrmLite - - - Add support for [cloning SqlExpressions](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/Expression/ExpressionChainingUseCase.cs#L192-L207) - - Add example of [migrating SqlServer TIME column to BigInteger](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/AdoNetDataAccessTests.cs) - - Add example of [calling Stored Procedures with OrmLite vs ADO.NET](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/TypeWithByteArrayFieldTests.cs#L55-L147) - - Add support for [MaxText in all DB providers](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/TypeDescriptorMetadataTests.cs#L57-L96) with `[StringLength(StringLengthAttribute.MaxText)]` - - Capture the LastSql Run even for queries with exceptions - -## Redis - - - Use enhanced functionality for when newer versions of redis-server exists - - i.e. Use more precise EXPIRE operations when server supports it - - Add `GetServerTime()` - -## ServiceStack.Text - - - Moved `JsConfig.RegisterForAot()` to `PclExport.RegisterForAot()` - - Fine-grained AOT hints available on `IosPclExport` static methods in PCL builds - -## Breaking Changes - -The [ServiceStack.Stripe](https://www.nuget.org/packages/ServiceStack.Stripe/) NuGet package is now a normal .NET 4.0 release. A new portable NuGet package was created for PCL clients at [ServiceStack.Stripe.Pcl](https://www.nuget.org/packages/ServiceStack.Stripe.Pcl/). - -# v4.0.11 Release Notes - -## OrmLite - -This release saw a lot of effort towards adding new features to OrmLite: - -### Pluggable Complex Type Serializers - -One of the [most requested features](http://servicestack.uservoice.com/forums/176786-feature-requests/suggestions/4738945-allow-ormlite-to-store-complex-blobs-as-json) -to enable pluggable serialization for complex types in OrmLite is now supported. This can be used to specify different serialization strategies for each -available RDBMS provider, e.g: - -```csharp -//ServiceStack's JSON and JSV Format -SqliteDialect.Provider.StringSerializer = new JsvStringSerializer(); -PostgreSqlDialect.Provider.StringSerializer = new JsonStringSerializer(); -//.NET's XML and JSON DataContract serializers -SqlServerDialect.Provider.StringSerializer = new DataContractSerializer(); -MySqlDialect.Provider.StringSerializer = new JsonDataContractSerializer(); -//.NET XmlSerializer -OracleDialect.Provider.StringSerializer = new XmlSerializableSerializer(); -``` -You can also provide a custom serialization strategy by implementing -[IStringSerializer](https://github.com/ServiceStack/ServiceStack.Text/blob/master/src/ServiceStack.Text/IStringSerializer.cs). - -By default all dialects use the existing JsvStringSerializer, except for PostgreSQL which due to its built-in support for JSON, now uses the JSON format by default. - -#### Breaking Change - -Using JSON as a default for PostgreSQL may cause issues if you already have complex types blobbed with the previous JSV Format. -You can revert back to the old behavior by resetting it back to the JSV format with: - -```csharp -PostgreSqlDialect.Provider.StringSerializer = new JsvStringSerializer(); -``` - -### New Global Insert / Update Filters - -Similar to interceptors in some heavy ORM's, new Insert and Update filters were added which get fired just before any **insert** or **update** operation using OrmLite's typed API's (i.e. not dynamic SQL or partial updates using anon types). -This functionality can be used for easily auto-maintaining Audit information for your POCO data models, e.g: - -```csharp -public interface IAudit -{ - DateTime CreatedDate { get; set; } - DateTime ModifiedDate { get; set; } - string ModifiedBy { get; set; } -} - -OrmLiteConfig.InsertFilter = (dbCmd, row) => { - var auditRow = row as IAudit; - if (auditRow != null) - auditRow.CreatedDate = auditRow.ModifiedDate = DateTime.UtcNow; -}; - -OrmLiteConfig.UpdateFilter = (dbCmd, row) => { - var auditRow = row as IAudit; - if (auditRow != null) - auditRow.ModifiedDate = DateTime.UtcNow; -}; -``` - -Which will ensure that the `CreatedDate` and `ModifiedDate` fields are populated on every insert and update. - -### Validation - -The filters can also be used for validation where throwing an exception will prevent the operation and bubble the exception, e.g: - -```csharp -OrmLiteConfig.InsertFilter = OrmLiteConfig.UpdateFilter = (dbCmd, row) => { - var auditRow = row as IAudit; - if (auditRow != null && auditRow.ModifiedBy == null) - throw new ArgumentNullException("ModifiedBy"); -}; - -try -{ - db.Insert(new AuditTable()); -} -catch (ArgumentNullException) { - //throws ArgumentNullException -} - -db.Insert(new AuditTable { ModifiedBy = "Me!" }); //succeeds -``` - -### Custom SQL Customizations - -A number of new hooks were added to provide more flexibility when creating and dropping your RDBMS tables. - -#### Custom Field Declarations - -The new `[CustomField]` can be used for specifying custom field declarations in the generated Create table DDL statements, e.g: - -```csharp -public class PocoTable -{ - public int Id { get; set; } - - [CustomField("CHAR(20)")] - public string CharColumn { get; set; } - - [CustomField("DECIMAL(18,4)")] - public decimal? DecimalColumn { get; set; } -} - -db.CreateTable(); -``` - -Generates and executes the following SQL: - -```sql -CREATE TABLE "PocoTable" -( - "Id" INTEGER PRIMARY KEY, - "CharColumn" CHAR(20) NULL, - "DecimalColumn" DECIMAL(18,4) NULL -); -``` - -#### Pre / Post Custom SQL Hooks when Creating and Dropping tables - -A number of custom SQL hooks were added that allow you to inject custom SQL before and after tables are created or dropped, e.g: - -```csharp -[PostCreateTable("INSERT INTO TableWithSeedData (Name) VALUES ('Foo');" + - "INSERT INTO TableWithSeedData (Name) VALUES ('Bar');")] -public class TableWithSeedData -{ - [AutoIncrement] - public int Id { get; set; } - public string Name { get; set; } -} -``` - -And just like other ServiceStack attributes, they can also be added dynamically, e.g: - -```csharp -typeof(TableWithSeedData) - .AddAttributes(new PostCreateTableAttribute( - "INSERT INTO TableWithSeedData (Name) VALUES ('Foo');" + - "INSERT INTO TableWithSeedData (Name) VALUES ('Bar');")); -``` - -Custom SQL Hooks are now available to execute custom SQL before and after a table has been created or dropped, i.e: - -```csharp -[PreCreateTable(runSqlBeforeTableCreated)] -[PostCreateTable(runSqlAfterTableCreated)] -[PreDropTable(runSqlBeforeTableDropped)] -[PostDropTable(runSqlAfterTableDropped)] -public class Table {} -``` - -### Re-factoring OrmLite's SQLite NuGet Packages - -In their latest release, the SQLite dev team maintaining the [core SQLite NuGet packages](https://www.nuget.org/profiles/mistachkin/) -have added a dependency to Entity Framework on their existing Sqlite NuGet packages forcing the installation of Entity Framework for users of OrmLite Sqlite. -This change also caused some users to see invalid web.config sections after applying the new web.config.transforms. -After speaking to the maintainers they've created a new -[System.Data.SQLite.Core](http://www.nuget.org/packages/System.Data.SQLite.Core) -NuGet package without the entity framework dependency and the problematic web.config.transforms. - -Unfortunately this was only added for their bundled x86/x64 NuGet package and not their other -[System.Data.SQLite.x86](http://www.nuget.org/packages/System.Data.SQLite.x86/) and -[System.Data.SQLite.x64](http://www.nuget.org/packages/System.Data.SQLite.x64/) which the team have indicated should be deprecated -in favor of the x86/x64 bundled **System.Data.SQLite.Core** package. - -As a result of this we're removing the dependency to the Sqlite NuGet packages in both architecture specific -[ServiceStack.OrmLite.Sqlite32](http://www.nuget.org/packages/ServiceStack.OrmLite.Sqlite32/) and -[ServiceStack.OrmLite.Sqlite64](http://www.nuget.org/packages/ServiceStack.OrmLite.Sqlite64/) packages and have -instead embedded the Sqlite binaries directly, which will solve the current issues and shield them from any future changes/updates -from the upstream Sqlite packages. - -#### New ServiceStack.OrmLite.Sqlite.Windows NuGet package - -Both these arch-specific packages should now be deprecated in favour of a new Sqlite NuGet package supporting both x86/x64 architectures on Windows: - - PM> Install-Package ServiceStack.OrmLite.Sqlite.Windows - -Which should now be used for future (or existing) projects previously using the old -[OrmLite.Sqlite32](http://www.nuget.org/packages/ServiceStack.OrmLite.Sqlite32/) and -[OrmLite.Sqlite64](http://www.nuget.org/packages/ServiceStack.OrmLite.Sqlite64/) packages. - -The Windows-specific package was added in addition to our existing Mono and Windows compatible release: - - PM> Install-Package ServiceStack.OrmLite.Sqlite.Mono - -Which works cross-platform on Windows and Linux/OSX with Mono should you need cross-platform support. - -## .NET Service Clients - -New async API's were added for requests marked with returning `IReturnVoid`. -This provides a typed API for executing services with no response that was previously missing, e.g: - -```csharp -public class Request : IReturnVoid {} - -await client.PostAsync(new Request()); -``` - -The API's for all sync and async REST operations have been changed to return `HttpWebResponse` which now lets you query the returned HTTP Response, e.g: -```csharp -HttpWebResponse response = await client.PostAsync(new Request()); -var api = response.Headers["X-Api"]; -``` - -## Authentication - -### New IManageRoles API - -A new [IManageRoles API](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/IAuthRepository.cs#L26) -was added that IAuthRepository's can implement in order to provide an alternative strategy for querying and managing Users' -Roles and permissions. - -This new API is being used in the `OrmLiteAuthRepository` to provide an alternative way to store -Roles and Permission in their own distinct table rather than being blobbed with the rest of the User Auth data. -You can enable this new behavior by specifying `UseDistinctRoleTables=true` when registering the OrmLiteAuthRepository, e.g: - -```csharp -container.Register(c => -new OrmLiteAuthRepository(c.Resolve()) { - UseDistinctRoleTables = true, -}); -``` - -When enabled, roles and permissions are persisted in the distinct **UserAuthRole** table. -This behavior is integrated with the rest of ServiceStack including the Users Session, RequiredRole/RequiredPermission attributes and the AssignRoles/UnAssignRoles authentication services. -Examples of this can be seen in [ManageRolesTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Common.Tests/ManageRolesTests.cs). - -## [Messaging](https://github.com/ServiceStack/ServiceStack/wiki/Messaging) - -### Flexible Queue Name strategies - -There are now more flexible options for specifying the Queue Names used in [ServiceStack's MQ Servers](https://github.com/ServiceStack/ServiceStack/wiki/Messaging). -You can categorize queue names or avoid conflicts with other MQ services by specifying a global prefix to be used for all Queue Names, e.g: - -```csharp -QueueNames.SetQueuePrefix("site1."); - -QueueNames.In //= site1.mq:Hello.inq -``` - -Or to gain complete control of each queue name used, provide a custom QueueName strategy, e.g: - -```csharp -QueueNames.ResolveQueueNameFn = (typeName, suffix) => - "SITE.{0}{1}".Fmt(typeName.ToLower(), suffix.ToUpper()); - -QueueNames.In //= SITE.hello.INQ -``` - -> Note: Custom QueueNames need to be declared on both MQ Client in addition to ServiceStack Hosts. - -# v4.10 Release Notes - -## Debug Links - -To provide better visibility to the hidden functionality in ServiceStack we've added **Debug Info** links section to the `/metadata` page which add links to any Plugins with Web UI's, e.g: - -![Debug Info Links](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/debug-links.png) - -The Debug Links section is only available in **DebugMode** (recap: set by default in Debug builds or explicitly with `Config.DebugMode = true`). In addition, users with the **Admin** role (or if `Config.AdminAuthSecret` is enabled) can also view the debug Plugins UI's in production. - -You can add links to your own [Plugins](https://github.com/ServiceStack/ServiceStack/wiki/Plugins) in the metadata pages with: - -```csharp -appHost.GetPlugin().AddPluginLink("swagger-ui/", "Swagger UI"); -appHost.GetPlugin().AddDebugLink("?debug=requestinfo", "Request Info"); -``` - -`AddPluginLink` adds links under the **Plugin Links** section and should be used if your plugin is publicly visible, otherwise use `AddDebugLink` for plugins only available during debugging or development. - -## [Auto Mapping](https://github.com/ServiceStack/ServiceStack/wiki/Auto-mapping) - -#### Improved Support for non-POCO types -Previously you could only map between top-level POCO models, now you can map between scalars and collections directly, e.g: - -```csharp -var intVal = 2L.ConvertTo(); -var decimalVal = 4.4d.ConvertTo(); -var usersSet = new[] { new User(1), new User(2) }.ConvertTo>(); -``` - -#### Improved Auto-Mapping Performance - -A better caching strategy is used for conversions paths and now mapping fields utilize cached Delegate expressions so POCO's with fields Map much faster. - -## Async Support - -#### Consistent handling of Async Responses - -Previously Response Filters were called with the Task response returned from async services for the Response DTO, e.g. `Task`. The response filters are now chained to the task so Response filters see the same native `TResponse` DTO that are passed in from Sync services. - -#### Async services can now be used in MQ Servers - -Async responses now block for results which is in-line with sync Services behavior where Message Queue Handlers only process one message at a time for each worker thread assigned to the Request type. - -## NuGet packages specify min versions - -To ensure NuGet pulls the latest dependencies when installing any ServiceStack package, a minimum version is now specified for all NuGet package dependencies. This [should alleviate dependency issues](http://stackoverflow.com/a/21670294/85785) people are seeing from NuGet's default behavior of pulling down old packages. - -# v4.09 Release Notes - -## Rabbit MQ Support - -The biggest feature in this release is ServiceStack's new support for -[hosting Services via a Rabbit MQ Server](https://github.com/ServiceStack/ServiceStack/wiki/Rabbit-MQ), -expanding on our existing [Redis MQ and In Memory messaging](https://github.com/ServiceStack/ServiceStack/wiki/Messaging) options -with a new durable MQ option in the robust and popular [Rabbit MQ](http://www.rabbitmq.com). -ServiceStack's Rabbit MQ support is available on NuGet with: - - PM> Install-Package ServiceStack.RabbitMq - -A new [Rabbit MQ on Windows installation and setup guide](https://github.com/mythz/rabbitmq-windows) was published containing -code samples for working with Rabbit MQ from C#/.NET. - -### Configurable Metadata Pages - -New customizable filters were added to the `MetadataFeature` plugin to allow customization of the Master and detail metadata pages before they're rendered. -E.g. you can reverse the order of operation names with: - -```csharp -var metadata = (MetadataFeature)Plugins.First(x => x is MetadataFeature); -metadata.IndexPageFilter = page => { - page.OperationNames.Sort((x,y) => y.CompareTo(x)); -}; -``` - -### OrmLite new runtime typed API - -The [IUntypedApi](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite/IUntypedApi.cs) interface is useful for when you only have access to a late-bound object runtime type which is accessible via `db.CreateTypedApi`, e.g: - -```csharp -public class BaseClass -{ - public int Id { get; set; } -} - -public class Target : BaseClass -{ - public string Name { get; set; } -} - -var row = (BaseClass)new Target { Id = 1, Name = "Foo" }; - -var useType = row.GetType(); -var typedApi = db.CreateTypedApi(useType); - -db.DropAndCreateTables(useType); - -typedApi.Save(row); - -var typedRow = db.SingleById(1); -typedRow.Name //= Foo - -var updateRow = (BaseClass)new Target { Id = 1, Name = "Bar" }; - -typedApi.Update(updateRow); - -typedRow = db.SingleById(1); -typedRow.Name //= Bar - -typedApi.Delete(typedRow, new { Id = 1 }); - -typedRow = db.SingleById(1); //= null -``` - -#### OrmLite Create Table Support - - - Added NonClustered and Clustered options to `[Index]` attribute - -## Breaking changes - -### Messaging - -In order to support Rabbit MQ Server some changes were made to -[ServiceStack's Messaging API](https://github.com/ServiceStack/ServiceStack/wiki/Messaging) to support all MQ options, namely: - - - `IMessageQueueClient` now exposes high-level `IMessage` API's instead of raw `byte[]` - - The `IMessage.Error` property is now a `ResponseStatus` type (same used in Web Services) - - **Ack** / **Nak** APIs were also added to `IMessageQueueClient` - - All MQ Brokers now have a default `RetryCount=1` - -### ServiceStack.Text - - - UrlEncode extension method now encodes spaces with `+` instead of `%20` to match default `HttpUtility.UrlEncode` behavior - -### OrmLite - - - MySql and Sqlite providers now treat GUID's as `char(36)` - -# v4.08 Release Notes - -Added new [ServiceStack/Stripe](https://github.com/ServiceStack/Stripe) GitHub repository containing a PCL typed, message-based API client gateway for [Stripe's REST API](https://stripe.com/docs/api/). Install from NuGet with: - - Install-Package ServiceStack.Stripe - -New in this release: - - - .NET 4.0 build of **ServiceStack.Razor** now available (in addition to .NET 4.5) - - New **Signed** NuGet packages published for - - [ServiceStack.Api.Swagger.Signed](https://www.nuget.org/packages/ServiceStack.Api.Swagger.Signed/) - - [ServiceStack.OrmLite.Oracle.Signed](https://www.nuget.org/packages/ServiceStack.OrmLite.Oracle.Signed/) - - Updated Swagger UI content files - - Added MiniProfiler SqlServerStorage adapter to **ServiceStack.Server** - - The [Razor Rockstars](https://github.com/ServiceStack/RazorRockstars/) and [Social Bootstrap Api](https://github.com/ServiceStack/SocialBootstrapApi/) projects have both been upgraded to v4 - -### OrmLite - - - Enums with `[Flag]` attribute (aka Enum flags) now stored as ints - - `TimeSpan` now stores ticks as longs for all DB providers (Breaking change for Sqlite) - -# v4.06 Release Notes - -## Portable Class Library Clients! - -The biggest feature of this release is the release of the new Portable Client NuGet packages: - -[![Portable Class Library Support](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/hello-pcl.png)](https://github.com/ServiceStackApps/HelloMobile) - - - ServiceStack.Interfaces.Pcl - - PCL Profiles: iOS, Android, Windows8, .NET 4.5, Silverlight5, WP8 - - ServiceStack.Client.Pcl - - PCL Profiles: iOS, Android, Windows8, .NET 4.5 - - Custom builds: Silverlight 5 - - ServiceStack.Text.Pcl - - PCL Profiles: iOS, Android, Windows8, .NET 4.5 - - Custom builds: Silverlight 5 - -This now allows sharing binaries between the above platforms. To illustrate this a new [Hello Repository](https://github.com/ServiceStackApps/HelloMobile) was created to show how to use the same portable class libraries and DTO's across the different client platforms above. - -#### Breaking Changes - -Adding PCL support to the client libraries involved a lot of internal re-factoring which caused a few external user-facing changes: - - - The `IDbConnectionFactory` and `IHasDbConnection` interfaces referencing System.Data was moved to ServiceStack.Common - - Properties exposing the concrete `NameValueCollection` are now behind an `INameValueCollection` interface - - Dynamic classes like `DynamicJson` have been moved under the `ServiceStack` namespace - -### Improved SOAP Support - -For maximum compatibility with different SOAP clients, SOAP Exceptions are now treated as "Soft HTTP Errors" where exceptions -are automatically converted to a **200 OK** but returns the original Status Code in the `X-Status` HTTP Response header or `X-Status` SOAP Header. - -Errors can be detected by looking at the X-Status headers or by checking the **ResponseStatus.ErrorCode** property on the Response DTO. -This is transparently handled in ServiceStack's built-in SoapClients which automatically converts Response Errors into populated -C# WebServiceExceptions, retaining the same behavior of ServiceStack's other typed clients, as seen in -[WebServicesTests](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/AlwaysThrowsService.cs#L162). - -IHttpRequest.OperationName now reports the Request DTO name for SOAP requests as well, which it gets from the SOAPAction HTTP Header in SOAP 1.1 requests or the **Action** SOAP Header for SOAP 1.2 Requests. - -# ServiceStack V4 Release Notes - -We're happy to announce that after months of intense development, v4-beta of ServiceStack has finally been released to NuGet! - -As [announced in August](https://plus.google.com/+DemisBellot/posts/g8TcZaE7bv9) to ensure it's continued development, ServiceStack has moved to a self-sustaining commercial model for commercial usage of ServiceStack from **v4+ onwards**. It's the first time we've been able to commit full-time resources to the project and is what has ensured continued investment and enabled v4 to be possible, with even more exciting features in the pipeline and roadmap for 2014. - -#### Free Usage for Small and OSS Projects - -We're also happy to announce that v4 includes [free quotas](https://servicestack.net/download#free-quotas) allowing the free usage of all of ServiceStack for small projects and evaluation purposes. Whilst OSS projects are able to use the source code on GitHub under the [AGPL/FOSS License Exception](https://github.com/ServiceStack/ServiceStack/blob/master/license.txt), and the older [v3 of ServiceStack](https://github.com/ServiceStackV3/ServiceStackV3) continues to be available under the [BSD license](https://github.com/ServiceStack/ServiceStack/blob/v3/LICENSE). - -#### Upgrading from v3 - -Whilst we recommend starting with **v4** for greenfield projects, v4 has seen significant changes since v3 that will require some development effort to upgrade. During the upgrade we recommend using a tool like [ReSharper](http://www.jetbrains.com/resharper/) to be able to easily find and update reference of any types that have moved. - -# What's new in v4 - -The major version upgrade of ServiceStack to v4 has provided us a long sought **breaking window** opportunity allowing us to re-factor, simplify, clean-up and fix all the warts and cruft that has been lingering in the ServiceStack code-base since its beginning - that due to backwards compatibility we were reluctant to remove. Whilst v4 has seen significant changes to the code-base, all existing tests are passing again with additional tests added for new functionality. - -We managed to retain a lot of the user-facing API's (E.g New API, AppHost, Config) which were already considered ideal so ideally upgrading shouldn't be too disruptive in the normal use-cases. - -v4 provides us a great foundation to build on that will be further improved during the beta by focusing on stability and fixing any reported issues as well as updating existing documentation to match v4's implementation and publish new examples showcasing v4's new features. - -## The big refactor of v4 - -This was the biggest re-factor in ServiceStack's history which at the end resulted in a much leaner, simplified, consistent and internal logically-structured code-base that's much easier to reason about, where even before adding any features the main ServiceStack repository saw: - - 1,192 changed files with 18,325 additions and 29,505 deletions. - -The number of deletions is indicative of how much legacy code was able to be removed, with much of the internals having been heavily restructured. Some of the highlights during the re-factor include: - - - All projects have been upgraded to .NET 4.0, except ServiceStack.Razor which is .NET 4.5 to use the latest version of Razor - - All obsolete/unused/shims/duplicate functionality and built-up cruft has now been removed (inc. the Old Api). - - State and configuration are now cohesively organized where now all AppHost's share the same `ServiceStackHost` base class which now maintains all state in ServiceStack, inc. the empty `BasicAppHost` that's used for unit testing which now shares much of the same state/context as Integration tests. - - Many namespaces and some concepts have been collapsed (e.g 'Endpoint'), resulting in ServiceStack projects requiring fewer namespaces - - All DTO's and extension methods and common user-facing classes have been moved to the base `ServiceStack` namespace - allowing them to be much easier to find. - - Re-organization of projects, **NuGet packages now map 1:1 with ServiceStack projects** for finer-grained control of dependencies: - + **ServiceStack.Interfaces** NuGet project created and ServiceInterface has been merged into **ServiceStack** - + **ServiceStack** NuGet package now only depends **ServiceStack.Common** and **ServiceStack.Client** - + A new **ServiceStack.Server** project exists for functionality requiring dependencies on OrmLite or Redis, inc. RedisMqServer and OrmLiteAuthRepository. - + **ServiceStack.Client** contains all the HTTP, SOAP and MQ Service Clients that have been split from **ServiceStack.Common** and only depends on ServiceStack.Interfaces and ServiceStack.Text (making it easier to maintain custom builds in future). - - EndpointHostConfig is now `HostConfig` and is limited to just Configuration, e.g. handlers like `CustomErrorHttpHandlers`, `RawHttpHandlers`, `GlobalHtmlErrorHttpHandler` have been moved to ServiceStackHost. - - EndpointHost is gone and replaced by the static `HostContext` class which doesn't contain any state itself, it's just a static convenience wrapper around `ServiceStackHost.Instance` (where all state is maintained). - - Removed all 'where T:' constraints where possible - - Removed `ConfigurationResourceManager`, use `AppSettings` instead - - The `ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory` used in Web.config's handler mapping has been renamed to just `ServiceStack.HttpHandlerFactory` - - `Config.ServiceStackHandlerFactoryPath` has been renamed to `Config.HandlerFactoryPath`. - - Predefined routes have been renamed from `/syncreply`, `/asynconeway` to just `/reply`, `/oneway` - - ServiceManager has been merged into `ServiceController`. - - The **ServiceStack.Logging** and **ServiceStack.Contrib** v4 projects have been merged into the major ServiceStack repo. - - The dynamic session `base.Session` has been renamed to `base.SessionBag` to better reflect its semantics. - - The [Auto Mapping](https://github.com/ServiceStack/ServiceStack/wiki/Auto-mapping) Utils extension methods were renamed from `TFrom.TranslateTo()` to `TFrom.ConvertTo()`. - - The `RequestFilters` and `ResponseFilters` were renamed to `GlobalRequestFilters` and `GlobalResponseFilters` which matches naming in the client `ServiceClientBase.GlobalRequestFilter`. - - New `GlobalMessageRequestFilters` and `GlobalMessageResponseFilters` have been added which are instead used by non-HTTP endpoints use, e.g. MQ. - - `CustomHttpHandlers` has been renamed to `CustomErrorHttpHandlers` - - The **LocalHttpWebRequestFilter** and **LocalHttpWebResponseFilter** in the Service Clients were renamed to just `RequestFilter` and `ResponseFilter` - - The Global **HttpWebRequestFilter** and **HttpWebResponseFilter** filters were also renamed to `GlobalRequestFilter` and `GlobalResponseFilter` respectively. - -### RequestContext now merged into new IRequest / IResponse classes: - -An annoyance remaining in the ServiceStack code-base was RequestContext and its relationship with its IHttpRequest and IHttpResponse classes. This was originally modeled after ASP.NET's relationship with HttpContext and its child HttpRequest/HttpResponse classes. Pragmatically speaking this model isn't ideal, as there was functionality spread across all 3 classes, many times duplicated. It was also not obvious how to retrieve IHttpRequest/IHttpResponse classes from a RequestContext and creating a RequestContext from outside of ServiceStack required more knowledge and effort than it should have. - -The new model adopts a flattened structure similar to Dart's server HttpRequest (http://bit.ly/19WUxLJ) which sees the `IRequestContext` eliminated in favour of a single `IRequest` class that also makes available direct access to the Response. - -This now becomes much easier to create a Request from outside of ServiceStack with an ASP.NET or HttpListener HttpContext e.g: - -```csharp -var service = new MyService { - Request = HttpContext.Current.ToRequest() -} - -var service = new MyService { - Request = httpListenerContext.ToRequest() -} -``` - -There's also direct access to the Response from a Request with: - -```csharp -IResponse response = Request.Response; -``` - -#### ASP.NET wrappers now only depends on HttpContextBase - -Also the ASP.NET `IHttpRequest` wrappers bind to the newer and mockable HttpContextBase / HttpRequestBase / HttpResponseBase classes which now makes it easier to call services from newer web frameworks like MVC with: - -```csharp -var service = new MyService { - Request = base.HttpContext.ToRequest() -} -``` - -The biggest user-facing change was renaming the IHttpRequest/IHttpResponse classes to IRequest/IResponse which is more indicative to what they represent, i.e. the Request and Response classes for all endpoints including MQ and future TCP endpoints. Now only HTTP Requests implement IHttpRequest/IHttpResponse which lets you add logic targeting only HTTP Services with a simple type check: - -```csharp -var httpReq = request as IHttpRequest; -if (httpReq != null) { - //Add logic for HTTP Requests... -} -``` - -Accessing the IHttpResponse works the same way, e.g: - -```csharp -var httpRes = Request.Response as IHttpResponse; -if (httpRes != null) { - //... -} -``` - -We're still going to add extension methods on IRequest/IResponse to make it easier to discover new functionality, but for HTTP functionality on non-HTTP requests these would just be a NO-OP rather than throw an exception. - -### Community v4 migration notes - - - [Upgrading Servicestack to 4.0 – Notes](http://www.binoot.com/2014/02/23/upgrading-servicestack-to-4-0-notes/) by [@binu_thayamkery](https://twitter.com/binu_thayamkery) - - [Upgrading OrmLite and ServiceStack to v4](http://camtucker.blogspot.ca/2014/01/updating-to-servicestack-v40.html?view=classic) by [@camtucker](http://camtucker.blogspot.ca/) - ----- - -# New Features in v4 - - -## Server-side Async Support - -The [most requested feature](http://bit.ly/16qCiy1), Server-side async support has now been implemented! This was surprisingly easy to do where now all HttpHandlers in ServiceStack inherit from a common `HttpAsyncTaskHandler` base class that now implements `IHttpAsyncHandler`. This lets you return an async Task from your Service in any number of ways as shown in http://bit.ly/1cOJ3hR - -E.g. Services can now have either an object, Task or async Task return types that can return a started or non-started task (which we'll start ourselves). This transition went as smooth as it could where all existing services continuing to work as before and all tests passing. - -## [ServiceStack Client](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) Task-based Async - -In matching the new server-side async story and now that all projects have been upgraded to .NET 4.0, all Service Clients have been changed to return .NET 4.0 Task's for all async operations so they can be used in C#'s async/await methods. Some examples of Async in action: http://bit.ly/17ps94C - -The Async API's also provide a **OnDownloadProgress** callback which you can tap into to provide a progress indicator in your UI, E.g: http://bit.ly/19ALXUW - -#### Use any Request DTO in Client API's - -ServiceClient API's that used to only accept Request DTO's with a `IReturn` marker, now have `object` overloads so they can be used for unmarked Request DTO's as well. - -### Custom Silverlight and Android builds - -We've added custom **Silverlight** and **Android** automated builds for ServiceStack.Client allowing the client libraries to be available in even more environments - with more to follow. - -## Signed NuGet Packages - -The following Signed NuGet packages are available for core ServiceStack projects in separate NuGet packages using the .Signed suffix: - - - ServiceStack.Client.Signed - - ServiceStack.Text.Signed - - ServiceStack.Redis.Signed - - ServiceStack.OrmLite.Signed - - ServiceStack.OrmLite.SqlServer.Signed - - ServiceStack.ServiceStack.Signed - - ServiceStack.ServiceStack.Razor.Signed - - ServiceStack.ServiceStack.Server.Signed - - ServiceStack.Common.Signed - -### ServiceStack.Interfaces is now strong-named - -In order to be able to have signed clients sharing types with non-signed ServiceStack instances, the DTO models and ServiceStack.Interfaces need to be signed. It was added in the most defensive way possible where **ServiceStack.Interfaces.dll** is the only dll that's strong-named by default. This should cause minimal friction as it is an impl-free assembly that rarely sees any changes. We're also keeping the AssemblyVersion which makes up the strong-name at a constant `4.0` whilst the benign AssemblyFileVersion will report the true version number. - -### Add Code-first Attributes at runtime, de-coupled from POCO's - -Inspection of all Metadata attributes in ServiceStack now uses ServiceStack.Text's attribute reflection API's which support adding of type and property metadata attributes dynamically. This now lets you add the same behavior normally only available via attributes, dynamically at StartUp. Some benefits of this include: being able to keep [unattributed data model POCOs in OrmLite](http://bit.ly/1e5IQqS) or to [extend built-in and external Request DTOs and Services](https://github.com/ServiceStack/ServiceStack/blob/d93ad805c8c8ffce8e32365e4217c65c19069cf0/tests/ServiceStack.WebHost.Endpoints.Tests/RuntimeAttributeTests.cs) with enhanced functionality that was previously only available using attributes. - -#### Fluent route configuration available in [Reverse Routing](https://github.com/ServiceStack/ServiceStack/wiki/Routing#reverse-routing) - -Leveraging the dynamic attribute support, we now include fluent Route definitions when retrieving relative or absolute urls in [Reverse Routing](https://github.com/ServiceStack/ServiceStack/wiki/Routing#reverse-routing), which can be used in Services when returning urls in responses and is also used in Service Clients to determine which routes to use. Note: as Fluent Routes are defined in the AppHost, they aren't registered and therefore not available in disconnected .NET client applications - so using `[Route]` attributes on Request DTO's remains the best way to share route definitions on both client and server. - -Priority was added to `[Route]` attributes so auto-generated routes are given less precedence than explicit user-defined custom routes when selecting the best matching route to use. - -### The Virtual FileSystem - -The Virtual FileSystem is now fully integrated into the rest of ServiceStack, this enables a few interesting things: - - - The `Config.WebHostPhysicalPath` sets where you want physical files in ServiceStack to be served from - - You can now access static files when ServiceStack is mounted at a custom path, e.g. /api/default.html will serve the static file at ~/default.html - - By Default, ServiceStack falls back (i.e when no physical file exists) to looking for Embedded Resource Files inside dlls. - - You can specify the number and precedence of which Assemblies it looks at with `Config.EmbeddedResourceSources` which by default looks at: - - The assembly that contains your AppHost - - **ServiceStack.dll** - -The VFS now elegantly lets you replace built-in ServiceStack templates with your own by simply copying the metadata or [HtmlFormat Template files](http://bit.ly/164YbrQ) you want to customize and placing them in your folder at: - - /Templates/HtmlFormat.html // The auto HtmlFormat template - /Templates/IndexOperations.html // The /metadata template - /Templates/OperationControl.html // Individual operation template - -This works because the ServiceStack.dll is the last assembly in `Config.EmbeddedResourceSources`. - -## API-first development - -We're starting to optimize ServiceStack's HTML story around an **API-first** style of web development (particularly well suited to ServiceStack) in which services are developed so they naturally support both web and native clients from the start. Effectively this means that the HTML views are just another client that escapes C# earlier and leverages JS+Ajax to provide its dynamic functionality, and any HTML-specific functionality is encouraged to be kept in Razor views rather than using post backs to generate different server-side HTML representations. - -Having developed the new [servicestack.net website](https://servicestack.net) in this way, we've found it to be a lot more productive and responsive than standard server-side MVC development that we we're accustomed to in .NET as JavaScript ends up being more mallable and flexible language with a smaller and reflective surface type area making it better suited in string manipulation, generating HTML views, consuming ajax services, event handling, DOM binding and manipulation, etc. - -We've begun taking advantage of the Virtual FileSystem to ship embedded resources enhancing ServiceStack's JS integration with client-side libraries like [ss-utils.js](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/js/ss-utils.js) that we maintain and update alongside the rest of ServiceStack's dlls. Whilst we intend to create more examples in the near future showcasing this functionality, here's an overview of what's been added: - - - ss-utils.js available in your local ServiceStack webhost at `/js/ss-utils.js` - - Inspired by AngularJS we've added **declarative** support over jQuery, letting you declaratively register and trigger events, bind values to HTML elements, register document handlers, etc, saving a lot of boilerplate than normal jQuery (more on this soon) - - Enhanced HTML forms with integration with ServiceStack validation, adds responsive UX/behavior, follows soft redirects - - Server-side responses can be decorated with Soft redirects with `HttpResult.SoftRedirect` or client events with `HttpResult.TriggerEvent` - - Use `("a").setActiveLinks()` to automatically set the active link and containing menu items for the current page - - Use `$("input").change($.ss.clearAdjacentError)` to clear highlighted errors as users correct their inputs - - Use `T.AsRawJson()` extension method to serialize C# models into JSON literals that are natively accessible in JS - - Use `T.ToGetUrl()`, `T.ToPostUrl()` to resolve service urls from typed Request DTOs (no code-gen required) - -## Improved Razor Support - -#### Improved Server-side validation - -The server-side validation story has also been improved with MVC's HTML INPUT and Validation Helpers rewritten to look at ServiceStack error responses (earlier lost in the upgrade to Razor 2.0) and making use of the same bootstrap conventional classes that the client-side Ajax validation uses letting you maintain a single style of error feedback for both validation styles. It also now looks at state contained in the POST'ed data when rendering the HTML INPUT controls. - -#### Fallback Routes - -The default Razor views are now also processed by the `FallbackRoute` if one exists, enhancing the story for Single Page Apps who want requests to un-specified routes to be handled by client-side routing instead of returning 404's. - -#### Pre-Request filters - -Direct (i.e. No Controller) Razor views and static file handlers now have pre-request filters applied to them, so they can be used for adding global behavior across all ServiceStack service and page requests. - -#### Precompilation option for Razor Views - -New options have been added to RazorFormat `PrecompilePages` and `WaitForPrecompilationOnStartup` that allow you to precompile razor views on startup and specify whether or not you want to wait for compilation to complete are now options available when registering the `RazorFormat`. As these can slow down dev iteration times they are not done when `Config.DebugMode` (aka development mode), but are otherwise enabled by default for production. - -#### Other Razor Improvements - - - More functionality was added to Razor Views matching the same API's available in ServiceStack's base `Service` class - - RenderSection/IsSectionDefined now looks in all connected views. - - `GetAbsoluteUrl`, `IsPostBack`, `GetErrorStatus()`, `GetErrorMessage()` convience methods added - -### CORS Feature - -CorsFeature now by default automatically handles all HTTP `OPTIONS` requests so you no longer have to explicitly allow for OPTION requests in your routes: http://bit.ly/19HbMVf - -Can be disabled with: - -```csharp -Plugins.Add(new CorsFeature { AutoHandleOptionsRequests = false }) -``` - -## Authentication - -The Auth Tables are now called **UserAuth** and **UserAuthDetails** and implements the IUserAuth and IUserAuthDetails interfaces. For advanced customization, these tables can now be extended using custom models inheriting these interfaces by using the generic AuthRepository types, e.g: - - - OrmLiteAuthRepository - - RedisAuthRepository - -Where the common non-generic **OrmLiteAuthRepository** is just a concrete impl inheriting from `OrmLiteAuthRepository`. Use `InitSchema()` to ensure missing Auth Tables are created at registration. - -#### New optional UserAuthRole table added - -A new `UserAuthRole` class was created for users who would prefer roles to be managed in separate tables rather than blobbed with the UserAuth table and session. E.g. You can change your custom session to check the database for asserting required users and permissions with: - -```csharp -public class CustomUserSession : AuthUserSession -{ - public override bool HasRole(string role) - { - using (var db = HostContext.TryResolve().Open()) - { - return db.Count(q => - q.UserAuthId == int.Parse(UserAuthId) && q.Role == role) > 0; - } - } - - public override bool HasPermission(string permission) - { - using (var db = HostContext.TryResolve().Open()) - { - return db.Count(q => - q.UserAuthId == int.Parse(UserAuthId) && q.Permission == permission) > 0; - } - } -} -``` - -#### Support for Max Login Attempts - -The `OrmLiteAuthRepository` now supports automatically locking out user accounts after reaching the maximum number of Login attempts which can be specified at registration, e.g: - -```csharp -container.Register(c => - new OrmLiteAuthRepository(c.Resolve()) { - MaxLoginAttempts = appSettings.Get("MaxLoginAttempts", 5) - }); -``` - -To opt-in to use the new locking behavior provide a value for `MaxLoginAttempts` as shown above. The above registration first uses the value overridable in appSettings if it exists, otherwise it defaults to a Maximum of 5 login attempts. - -#### Adhoc locking of User Accounts - -The `CredentialsAuthProvider` also supports locking user accounts by populating the `UserAuth.LockedDate` column with a non-null value. Set it back to null to unlock the account. - -#### Initializing Auth Repository Schemas - -Some Auth Repositories like OrmLite require an existing schema before they can be used, this can be done in the AppHost with: - -```csharp -//Create missing Auth Tables in any Auth Repositories that need them -container.Resolve().InitSchema(); -``` -This was previously named `CreateMissingTables()` and is safe to always run as it's a NO-OP for Auth repositories that don't require a schema and only creates missing tables, so is idempotent/non-destructive on subsequent runs. - -#### New AuthWeb Test project - -A new test project testing all Authentication providers within the same ServiceStack ASP.NET Web Application is in [ServiceStack.AuthWeb.Tests](https://github.com/ServiceStack/ServiceStack/tree/master/tests/ServiceStack.AuthWeb.Tests). - -### AppSettings - -AppSettings can now be passed a tier in the constructor, e.g. `new AppSettings(tier: "Live")` which it uses as a prefix to reference Tier-specific appSettings first, e.g: - - - -Before falling back to the common key without the prefix, i.e: - - - -AppSettings now allows a Parsing Strategy, e.g. You can collapse new lines when reading a complex configuration object in Web.Config `` with: - -```csharp -var appSettings = new AppSettings { - ParsingStrategy = AppSettingsStrategy.CollapseNewLines -}; -``` - -### Nested Request DTOs - -Using [nested types as Request DTO's](https://github.com/ServiceStack/ServiceStack/commit/376ca38f604214f4d12e2f7803d8e7cfc271b725) are now supported. -Nested Request DTO types include the names of their containing class to form their unique name, allowing the use of multiple nested types with the same name, which is potentially interesting to be used as a versioning strategy. - -### Localized symbols - -I've added `IAppHost.ResolveLocalizedString` support in [this commit](http://bit.ly/181q0eP) which lets you override the built-in English symbols used in ServiceStack, e.g. this lets you change built-in ServiceStack routes, e.g: `/auth`, `/assignroles`, `?redirect=`, etc. into something more appropriate for your language. - -## Other New Web Framework Features - - - Added convenient [Repository and Logic base classes](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/ILogic.cs) to reduce boilerplate when extracting logic from services into custom classes - - Added `IAppHost.OnExceptionTypeFilter` to be able to customize ResponseStatus based on Exception types. Used to change the [default behavior of ArgumentExceptions](https://github.com/ServiceStack/ServiceStack/commit/17985239ed6f84b3126c651dbacd0c760a4d2951) so that they're converted to field errors - - Added `IAppHost.OnServiceException` so service exceptions can be intercepted and converted to different responses - - Add `ConvertHtmlCodes` extension method converting HTML entities to hex-encoded entities - - Add `Config.ScanSkipPaths` option to skip any plugins using the VFS to scan the filesystem (e.g. Razor/Markdown feature) from scanning specified directories, `/bin/` and `/obj/` are added by default. - - Added a pre-defined `/swagger-ui/` route that loads the Swagger UI and auto configures it to look at ServiceStack services. A link to this is on the metadata page under **Plugin Links** heading. - - Added `ModelFilter` and `ModelPropertyFilter` to allow fine-grained custom control on what's displayed in the Swagger API - - Wrappers around .NET's JSON and XML DataContract Serializers now share the same `IStringSerializer` interface - - Added ToMsgPack/FromMsgPack and ToProtoBuf/FromProtoBuf extension methods - - Improved support for stripping App Virtual Paths when Resolving Absolute Urls useful when applications are hosted with virtual app paths as done in Amazon Web Services. This behavior can be enabled with `Config.StripApplicationVirtualPath = true`. - - Support for explicitly referencing ignored DTO properties in Route PathInfo definitions, but not QueryStrings - - Add support for getting Id property from runtime object type - - Added support for registering a singleton instance as a runtime type - - Added new [IRestGateway](https://github.com/ServiceStack/ServiceStack/commit/29d60dfa22424fe20ba35c8603686c05f88a6c25) interface that typed 3rd Party gateways can use to retain a consistent and mockable interface. Specialized MockRestGateway added to stub or mock out gateways to 3rd Party services - - `__requestinfo` is now available on any request with `?debug=requestinfo` and is accessible to administrators or when in **DebugMode**, and provides in-depth diagnostics about the details of the current request and the configured AppHost including Startup errors (if any). - - Plugins can register startup exceptions with `IAppHost.NotifyStartupException` - - Added new HTTP Headers on IHttpRequest for `XForwardedPort` and `XForwardedProtocol` - - Added `[EnsureHttps]` Request Filter to automatically redirect request if service was not requested under a Secure Connection with options to **SkipIfDebugMode** or **SkipIfXForwardedFor** to allow local development and requests via proxies / load-balancers in HTTP. - - Users in the **Admin** role have super-user access giving them access to all protected resources. You can also use `Config.AdminAuthSecret` to specify a special string to give you admin access without having to login by adding `?authsecret=xxx` to the query string. - ------ - -## OrmLite - -### Improved Consistency - -As the API surface of OrmLite expands it became a lot more important to focus on better consistency which now sees all alternative aliases having been removed in favor of standardized naming around SQL equivalents (e.g Select,Insert,etc). Also the parameterized APIs and the C#-like string.Format API's have now been merged with the parameterized APIs now being the default and the string.Format API having a 'Fmt' suffix. - -Most of these APIs now have XML docs and Examples for a better Intelli-sense experience. We've also provided them in a list along side it's generated SQL in [these API tests](http://bit.ly/1gmrnwe) - -Some notes: - - - `Select` returns a List - - `Single` returns 1 row (or null) if it doesn't exist - - `Scalar` returns a single a scalar value (e.g. int, long) - - `Where` is a short-hand for 'Select' that takes a single filter - - `Count` is a convenience that performs an aggregate SQL Count - - `Exists` returns true if there were any results - - `Lazy` suffix indicates the results are lazily streamed - - `Column` returns the first column results in a List - - `ColumnDistinct` returns the first column unique results in a HashSet - - `Dictionary` returns a Dictionary made up from the first 2 columns - - `Lookup` returns a LINQ-like grouping in a Dictionary> - - `NonDefaults` suffix indicates only non-null values are used in qry - - `Only` suffix allows you to specify fields used on the call-site - - `Sql` prefix are helpers for reading and querying arbitrary raw SQL - - `Save` is a convenience that inserts or updates depending if it exists or not. It also now populates AutoIncrementing Id's on Inserts. - - All batch operations like `InsertAll`, `UpdateAll`, `DeleteAll`, `SaveAll` participate in an existing transaction if 1 exists, otherwise a new one - - Removed all 'where T:' constraints where possible - - `OrDefault` APIs removed, All APIs now return null instead of throwing - - autoDisposeConnection removed. false for ":memory:" otherwise true - - Now that all OrmLite's parameterized `Query*` APIs have been merged (above), any `Query` APIs are from Dapper's extension method, which is also included in OrmLite under ServiceStack.OrmLite.Dapper namespace. - - All remaining OrmLIte Attributes have been moved to ServiceStack.Interfaces, which in future will be the only dependency needed by your data models and DTOs. - -### OrmLite extension methods are now mockable - -OrmLite API's can now be mocked by injecting a ResultsFilter letting you mock the results return by OrmLite which it will use instead of hitting the database. You can also mock with a filter function and it also supports nesting, see examples at: http://bit.ly/1aldecK - -This will be useful in Unit Testing Services that access OrmLite directly instead of using a repository. - -### Support for references, POCO style - -We've added a cool new feature to Store and Load related entities that works great on POCO which are enabled when you use the `[Reference]` attribute, e.g: http://bit.ly/1gmvtV6 - -Unlike normal complex properties in OrmLite: - - - Doesn't persist as complex type blob - - Doesn't impact normal querying - - Saves and loads references independently from itself - - Populated references get serialized in Text serializers (only populated are visible). - - Data is only loaded 1-reference-level deep - - Reference Fields require consistent `(T)Id` naming - -Basically it provides a better story when dealing with referential data that doesn't impact the POCO's ability to be used as DTO's. At the moment it's limited to loading and saving on a Single instance. We'll look at optimizations for batches on this in future. - -We're going to be giving OrmLite a lot more attention from now on given that we're working full-time on ServiceStack and are using it exclusively for our .NET RDBMS peristence. We also intend on adding specialized support to take advantage of PostgreSQL's new features like their HStore and native JSON support. PostgreSQL has been offering the best features of both RDBMS and NoSQL worlds lately and has recently become a particularly attractive option now that AWS is offering first-class support for PostgreSQL in both their RDS and Redshift services. - ------ -## ServiceStack.Text - - - Allow adding metadata attributes to types or attributes at runtime - - Add JsConfig.ExcludeTypes option to skip serialization of non-serializable properties like Streams - - Change QueryString's to also adopt the configured `JsConfig.PropertyConvention` and `JsConfig.EmitLowercaseUnderscoreNames` behavior - - Added an injectable ComplexTypeStrategy to the QueryStringSerializer that allows customizing the generation of complex types, e.g. can use a hash literal notation strategy with `QueryStringStrategy.FormUrlEncoded`. - - Added `typeof(T).New()` extension method providing a fast way of creating new instances of static or runtime types that will use factory functions registered in the centralized `JsConfig.ModelFactory` (if configured). - - The string "on" (i.e. the default value for HTML checkbox) is considered a **true** value for booleans (same with '1') - - The JSON serializers can be configured to support UnixTime and UnixTimeMs for DateTime's - - Renamed JsonDateHandler to `DateHandler` and JsonPropertyConvention to `PropertyConvention` - -### HTTP Utils are now mockable - -Following in the steps of now being able to Mock OrmLite, the [HTTP Utils](https://github.com/ServiceStack/ServiceStack/wiki/Http-Utils) extension methods (http://bit.ly/WyV2tn) are now mockable, e.g: - - using (new HttpResultsFilter { - StringResult = "mocked" - }) - { - //All return "mocked" - "http://google.com".GetJsonFromUrl(); - "http://google.com".GetXmlFromUrl(); - "http://google.com".GetStringFromUrl(accept: "text/csv"); - "http://google.com".PostJsonToUrl(json: "{\"postdata\":1}"); - } - -More examples showing how all HTTP Apis can be mocked are at: http://bit.ly/HdWmgm - ------ - -## New pre-release MyGet Feeds - -Instead of publishing pre-release packages on NuGet, we're instead going to release our interim packages to [MyGet](https://www.myget.org/) first which provides greater control and allows better management of packages. - -The Instructions to add ServiceStack's MyGet feed to VS.NET are: - - 1. Go to Tools -> Options -> Package Manager -> Package Sources - 2. Add the Source **https://www.myget.org/F/servicestack** with the name of your choice, e.g. _ServiceStack MyGet feed_ - ------ - -## [Older v3 Release Notes](https://github.com/ServiceStack/ServiceStack/wiki/Release-Notes-v3) diff --git a/docs/2015/release-notes.md b/docs/2015/release-notes.md deleted file mode 100644 index e4fdeecf1c5..00000000000 --- a/docs/2015/release-notes.md +++ /dev/null @@ -1,6628 +0,0 @@ -## Go to [2016 Release Notes](https://github.com/ServiceStack/ServiceStack/blob/master/docs/2016/release-notes.md) - ---- - -# v4.0.50 Release Notes - -This is primarily a bug fix release to -[resolve issues from the last release](https://github.com/ServiceStack/ServiceStack/blob/master/docs/2015/release-notes.md#v4048-issues) -that we wanted to get out before the holidays. This release also contains a number of performance improvements -added in OrmLite to speed up your Data Access and -[AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) results. - -Other changes in this release include: - -#### New OnSessionFilter - -You can intercept sessions after they've been resolved from the cache and modify them before they're used in -ServiceStack or other application code by overriding `OnSessionFilter()` in your AppHost, e.g: - -```csharp -public override IAuthSession OnSessionFilter(IAuthSession session, string withSessionId) -{ - // Update User Session - return base.OnSessionFilter(session, withSessionId); -} -``` - -This comes in useful when migrating existing sessions and populating properties with custom values. - -#### Registered Type Filters on IAppHost - -To make it easier for plugins to register -[Typed Filters](https://github.com/ServiceStack/ServiceStack/wiki/Request-and-response-filters#typed-request-filters) -, their Registration APIs are now available on IAppHost as well, e.g: - -```csharp -public interface IAppHost -{ - /// - /// Add Request Filter for a specific Request DTO Type - /// - void RegisterTypedRequestFilter(Action filterFn); - - /// - /// Add Request Filter for a specific Response DTO Type - /// - void RegisterTypedResponseFilter(Action filterFn); - - /// - /// Add Request Filter for a specific MQ Request DTO Type - /// - void RegisterTypedMessageRequestFilter(Action filterFn); - - /// - /// Add Request Filter for a specific MQ Response DTO Type - /// - void RegisterTypedMessageResponseFilter(Action filterFn); -} -``` - -## [RedisReact](https://github.com/ServiceStackApps/RedisReact) - -New Windows, OSX, Linux binaries published and -[http://redisreact.servicestack.net](http://redisreact.servicestack.net) -Live Demo updated with this November Release: - -#### Connections with Authentication - -Added support for password authentication when establishing connections with redis. - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/updates/add-authentication.png) - -#### Custom key console links - -The **console** link now populates the console with the most appropriate command for each key type, e.g. clicking **console** -ok a Sorted Set Key (ZSET) populates the Web Console with `ZRANGE key 0 -1 WITHSCORES`. - -## ServiceStack.Redis - -#### RedisConfig.DefaultMaxPoolSize - -You can easily configure the default pool size for `RedisManagerPool` and `PooledRedisClientManager` with -a global static configuration, e.g: - -```csharp -RedisConfig.DefaultMaxPoolSize = 200; -``` - -**Changes:** - -The `RedisManagerPool.MaxPoolSize` property is now read-only to reflect proper usage where it needs to be -specified in the constructor otherwise it's ignored. - -### New Redis APIs - -New API's added to typed Redis Client to make available API's to resolve cache key for specific types, -deprecate `SetEntry*` API's and replace them with more appropriately named `SetValue*`, allow typed API -to store and expire typed POCO's in 1 operation: - -```csharp -public interface IRedisClient -{ - //Resolve cache key for specific Type and Id - string UrnKey(T value); - string UrnKey(object id); - string UrnKey(Type type, object id); -} - -public interface IRedisTypedClient -{ - //resolve cache key used for a typed instance - string UrnKey(T value); - - //Deprecate SetEntry* API's - [Obsolete("Use SetValue()")] - void SetEntry(string key, T value); - [Obsolete("Use SetValue()")] - void SetEntry(string key, T value, TimeSpan expireIn); - [Obsolete("Use SetValueIfNotExists()")] - bool SetEntryIfNotExists(string key, T value); - - //Replaces above SetEntry* API's - void SetValue(string key, T entity); - void SetValue(string key, T entity, TimeSpan expireIn); - bool SetValueIfNotExists(string key, T entity); - bool SetValueIfExists(string key, T entity); - - //Save and expire an entity in 1 operation - T Store(T entity, TimeSpan expireIn); -} -``` - -### ServiceStack.Text - -To improve the usefulness of mocking HTTP Requests, the request body is now passed in the Results Filter -so the Request Body can be inspected, e.g: - -```csharp -using (new HttpResultsFilter -{ - StringResultFn = (webReq, reqBody) => - { - if (reqBody != null && reqBody.Contains("{\"a\":1}")) - return "mocked-by-body"; - - return webReq.RequestUri.ToString().Contains("google") - ? "mocked-google" - : "mocked-yahoo"; - } -}) -{ - "http://yahoo.com".PostJsonToUrl(json: "{\"a\":1}") //= mocked-by-body - - "http://google.com".GetJsonFromUrl() //= mocked-google - "http://yahoo.com".GetJsonFromUrl() //= mocked-yahoo -} -``` - -Previously [inspecting the Request Body was not possible](http://stackoverflow.com/a/31631039/85785). -Thanks to [@georgehemmings](https://github.com/georgehemmings) for adding this feature. - -# v4.0.48 Release Notes - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/servicestack-aws-banner-420.png) - -In this release we've started increasing ServiceStack's value beyond its primary focus of simple, fast and productive -libraries and started looking towards improving integration with outside environments for hosting ServiceStack Services. -This release marks just the beginning, we'll continue enhancing the complete story around developing, deploying and -hosting your ServiceStack solutions ensuring it provides seamless integration with the best Single Page Apps, Mobile/Desktop -technologies and Cloud/Hosting Services that share our simplicity, performance and value-focused goals that we believe -provide the best return on effort and have the most vibrant ecosystems. - -## .NET before Cloud Services - -One thing we've missed from being based on .NET is its predisposition towards Windows-only technologies, missing out on -all the industrial strength server solutions that are being primarily developed for hosting on Linux. This puts .NET -at a disadvantage to other platforms which have first-class support for using the best technologies at their discretion, -which outside of .NET, are primarily running on Linux servers. We've historically ignored this bias in .NET and have -always focused on simple technologies we've evaluated that provide the best value. Often this means we've had to maintain -rich .NET clients ourselves to get a great experience in .NET which is what led us to develop first-class -[Redis client](https://github.com/ServiceStack/ServiceStack.Redis) and why -[OrmLite](https://github.com/ServiceStack/ServiceStack.Redis) -has first-class support for major RDBMS running on Linux inc. PostgreSQL, MySql, Sqlite, Oracle and Firebird - -all the while ensuring ServiceStack's libraries runs cross-platform on Mono/Linux. - -## AWS's servicified platform and polyglot ecosystem - -By building their managed platform behind platform-agnostic web services, Amazon have largely eroded this barrier. We -can finally tap into the same ecosystem [innovative Startups are using](http://techstacks.io/tech/amazon-ec2) with -nothing more than the complexity cost of a service call - the required effort even further reduced with native clients. -Designing its services behind message-based APIs made it much easier for Amazon to enable a new polyglot world with -[native clients for most popular platforms](https://aws.amazon.com/dynamodb/developer-resources/#SDK), putting .NET -on a level playing field with other platforms thanks to [AWS SDK for .NET's](http://aws.amazon.com/sdk-for-net/) -well-maintained typed native clients. By providing its functionality behind well-defined services, for the first time -we've seen in a long time, .NET developers are able to benefit from this new polyglot world where solutions and app -logic written in other languages can be easily translated into .NET languages - a trait which has been invaluable whilst -developing ServiceStack's integration support for AWS. - -This also means features and improvements to reliability, performance and scalability added to its back-end servers benefit -every language and ecosystem using them. .NET developers are no longer at a disadvantage and can now leverage the same -platform Hacker Communities and next wave of technology leading Startups are built on, benefiting from the Tech Startup -culture of sharing their knowledge and experiences and pushing the limits of what's possible today. - -AWS offers unprecedented productivity for back-end developers, its servicified hardware and infrastructure encapsulates -the complexity of managing servers at a high-level programmatic abstraction that's effortless to consume and automate. -These productivity gains is why we've been running our public servers on AWS for more than 2 years. The vast array of -services on offer means we have everything our solutions need within the AWS Console, our RDS managed PostgreSQL databases -takes care of automated backups and software updates, ease of snapshots means we can encapsulate and backup the -configuration of our servers and easily spawn new instances. AWS has made software developers more capable than ever, -and with its first-class native client support leveling the playing field for .NET, there's no reason why -[the next Instagram](http://highscalability.com/blog/2012/4/9/the-instagram-architecture-facebook-bought-for-a-cool-billio.html) -couldn't be built by a small team of talented .NET developers. - -## ServiceStack + Amazon Web Services - -We're excited to participate in AWS's vibrant ecosystem and provide first-class support and deep integration with AWS where -ServiceStack's decoupled substitutable functionality now seamlessly integrates with popular AWS back-end technologies. -It's now more productive than ever to develop and host ServiceStack solutions entirely on the managed AWS platform! - -## ServiceStack.Aws - -All of ServiceStack's support for AWS is encapsulated within the single **ServiceStack.Aws** NuGet package which -references the latest modular AWSSDK **v3.1x** dependencies **.NET 4.5+** projects can install from NuGet with: - - PM> Install-Package ServiceStack.Aws - -This **ServiceStack.Aws** NuGet package includes implementations for the following ServiceStack providers: - - - **[PocoDynamo](#pocodynamo)** - Exciting new declarative, code-first POCO client for DynamoDB with LINQ support - - **[SqsMqServer](#sqsmqserver)** - A new [MQ Server](https://github.com/ServiceStack/ServiceStack/wiki/Messaging) for invoking ServiceStack Services via Amazon SQS MQ Service - - **[S3VirtualPathProvider](#S3virtualpathprovider)** - A read/write [Virtual FileSystem](https://github.com/ServiceStack/ServiceStack/wiki/Virtual-file-system) around Amazon's S3 Simple Storage Service - - **[DynamoDbAuthRepository](#dynamodbauthrepository)** - A new [UserAuth repository](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization) storing UserAuth info in DynamoDB - - **[DynamoDbAppSettings](#dynamodbappsettings)** - An [AppSettings provider](https://github.com/ServiceStack/ServiceStack/wiki/AppSettings) storing App configuration in DynamoDB - - **[DynamoDbCacheClient](#dynamodbcacheclient)** - A new [Caching Provider](https://github.com/ServiceStack/ServiceStack/wiki/Caching) for DynamoDB - -> We'd like to give a big thanks to [Chad Boyd](https://github.com/boydc7) from Spruce Media for contributing the SqsMqServer implementation. - -## [AWS Live Examples](http://awsapps.servicestack.net/) - -To demonstrate the ease of which you can build AWS-powered solutions with ServiceStack we've rewritten 6 of our existing -[Live Demos](https://github.com/ServiceStackApps/LiveDemos) to use a pure AWS managed backend using: - - - [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) for data persistance - - [Amazon S3](https://aws.amazon.com/s3/) for file storage - - [Amazon SQS](https://aws.amazon.com/sqs/) for background processing of MQ requests - - [Amazon SES](https://aws.amazon.com/ses/) for sending emails - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/awsapps.png)](http://awsapps.servicestack.net/) - -### Simple AppHost Configuration - -A good indication showing how simple it is to build ServiceStack + AWS solutions is the size of the -[AppHost](https://github.com/ServiceStackApps/AwsApps/blob/master/src/AwsApps/AppHost.cs) which contains all the -configuration for **5 different Apps** below utilizing all the AWS technologies listed above contained within a **single** -ASP.NET Web Application where each application's UI and back-end Service implementation are encapsulated under -their respective sub directories: - - - [/awsath](https://github.com/ServiceStackApps/AwsApps/tree/master/src/AwsApps/awsauth) -> [awsapps.servicestack.net/awsauth/](http://awsapps.servicestack.net/awsauth/) - - [/emailcontacts](https://github.com/ServiceStackApps/AwsApps/tree/master/src/AwsApps/emailcontacts) -> [awsapps.servicestack.net/emailcontacts/](http://awsapps.servicestack.net/emailcontacts/) - - [/imgur](https://github.com/ServiceStackApps/AwsApps/tree/master/src/AwsApps/imgur) -> [awsapps.servicestack.net/imgur/](http://awsapps.servicestack.net/imgur/) - - [/restfiles](https://github.com/ServiceStackApps/AwsApps/tree/master/src/AwsApps/restfiles) -> [awsapps.servicestack.net/restfiles/](http://awsapps.servicestack.net/restfiles/) - - [/todo](https://github.com/ServiceStackApps/AwsApps/tree/master/src/AwsApps/todo) -> [awsapps.servicestack.net/todo/](http://awsapps.servicestack.net/todo/) - -## [AWS Razor Rockstars](http://awsrazor.servicestack.net/) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/awsrazor.png)](http://awsrazor.servicestack.net/) - -### Maintain Website Content in S3 - -The -[implementation for AWS Razor Rockstars](https://github.com/ServiceStackApps/RazorRockstars/tree/master/src/RazorRockstars.S3) -is kept with all the other ports of Razor Rockstars in the [RazorRockstars repository](https://github.com/ServiceStackApps/RazorRockstars). -The main difference that stands out with [RazorRockstars.S3](https://github.com/ServiceStackApps/RazorRockstars/tree/master/src/RazorRockstars.S3) -is that all the content for the App is **not** contained within project as all its Razor Views, Markdown Content, imgs, -js, css, etc. are instead being served **directly from an S3 Bucket** :) - -This is simply enabled by overriding `GetVirtualFileSources()` and adding the new -`S3VirtualPathProvider` to the list of file sources: - -```csharp -public class AppHost : AppHostBase -{ - public override void Configure(Container container) - { - //All Razor Views, Markdown Content, imgs, js, css, etc are served from an S3 Bucket - var s3 = new AmazonS3Client(AwsConfig.AwsAccessKey, AwsConfig.AwsSecretKey, RegionEndpoint.USEast1); - VirtualFiles = new S3VirtualPathProvider(s3, AwsConfig.S3BucketName, this); - } - - public override List GetVirtualFileSources() - { - //Add S3 Bucket as lowest priority Virtual Path Provider - var pathProviders = base.GetVirtualFileSources(); - pathProviders.Add(VirtualFiles); - return pathProviders; - } -} -``` - -The code to import RazorRockstars content into an S3 bucket is trivial: we just use a local FileSystem provider to get -all the files we're interested in from the main ASP.NET RazorRockstars projects folder, then write them to the configured -S3 VirtualFiles Provider: - -```csharp -var s3Client = new AmazonS3Client(AwsConfig.AwsAccessKey, AwsConfig.AwsSecretKey, RegionEndpoint.USEast1); -var s3 = new S3VirtualPathProvider(s3Client, AwsConfig.S3BucketName, appHost); - -var fs = new FileSystemVirtualPathProvider(appHost, "~/../RazorRockstars.WebHost".MapHostAbsolutePath()); - -var skipDirs = new[] { "bin", "obj" }; -var matchingFileTypes = new[] { "cshtml", "md", "css", "js", "png", "jpg" }; -//Update links to reference the new S3 AppHost.cs + RockstarsService.cs source code -var replaceHtmlTokens = new Dictionary { - { "title-bg.png", "title-bg-aws.png" }, //S3 Title Background - { "https://gist.github.com/3617557.js", "https://gist.github.com/mythz/396dbf54ce6079cc8b2d.js" }, - { "https://gist.github.com/3616766.js", "https://gist.github.com/mythz/ca524426715191b8059d.js" }, - { "RazorRockstars.WebHost/RockstarsService.cs", "RazorRockstars.S3/RockstarsService.cs" }, -}; - -foreach (var file in fs.GetAllFiles()) -{ - if (skipDirs.Any(x => file.VirtualPath.StartsWith(x))) continue; - if (!matchingFileTypes.Contains(file.Extension)) continue; - - if (file.Extension == "cshtml") - { - var html = file.ReadAllText(); - replaceHtmlTokens.Each(x => html = html.Replace(x.Key, x.Value)); - s3.WriteFile(file.VirtualPath, html); - } - else - { - s3.WriteFile(file); - } -} -``` - -During the import we also update the links in the Razor `*.cshtml` pages to reference the new RazorRockstars.S3 content. - -### Update S3 Bucket to enable LiveReload of Razor Views and Markdown - -Another nice feature of having all content maintained in an S3 Bucket is that you can just change files in the S3 Bucket -directly and have all App Servers immediately reload the Razor Views, Markdown content and static resources without redeploying. - -#### CheckLastModifiedForChanges - -To enable this feature we just tell the Razor and Markdown plugins to check the source file for changes before displaying each page: - -```csharp -GetPlugin().CheckLastModifiedForChanges = true; -Plugins.Add(new RazorFormat { CheckLastModifiedForChanges = true }); -``` - -When this is enabled the View Engines checks the ETag of the source file to find out if it's changed, if it did, -it will rebuild and replace it with the new view before rendering it. -Given [S3 supports object versioning](http://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html) this feature -should enable a new class of use-cases for developing Content Heavy management sites with ServiceStack. - -#### Explicit RefreshPage - -One drawback of enabling `CheckLastModifiedForChanges` is that it forces a remote S3 call for each view before rendering it. -A more efficient approach is to instead notify the App Servers which files have changed so they can reload them once, -alleviating the need for multiple ETag checks at runtime, which is the approach we've taken with the -[UpdateS3 Service](https://github.com/ServiceStackApps/RazorRockstars/blob/e159bb9d2e27eba7fc1a9ce1822b479602de8e0f/src/RazorRockstars.S3/RockstarsService.cs#L139): - -```csharp -if (request.Razor) -{ - var kurtRazor = VirtualFiles.GetFile("stars/dead/cobain/default.cshtml"); - VirtualFiles.WriteFile(kurtRazor.VirtualPath, - UpdateContent("UPDATED RAZOR", kurtRazor.ReadAllText(), request.Clear)); - HostContext.GetPlugin().RefreshPage(kurtRazor.VirtualPath); //Force reload of Razor View -} - -var kurtMarkdown = VirtualFiles.GetFile("stars/dead/cobain/Content.md"); -VirtualFiles.WriteFile(kurtMarkdown.VirtualPath, - UpdateContent("UPDATED MARKDOWN", kurtMarkdown.ReadAllText(), request.Clear)); -HostContext.GetPlugin().RefreshPage(kurtMarkdown.VirtualPath); //Force reload of Markdown -``` - -#### Live Reload Demo - -You can test live reloading of the above Service with the routes below which modify Markdown and Razor views with the -current time: - - - [/updateS3](http://awsrazor.servicestack.net/updateS3) - Update Markdown Content - - [/updateS3?razor=true](http://awsrazor.servicestack.net/updateS3?razor=true) - Update Razor View - - [/updateS3?razor=true&clear=true](http://awsrazor.servicestack.net/updateS3?razor=true&clear=true) - Revert changes - -> This forces a recompile of the modified views which greatly benefits from a fast CPU and is a bit slow on our -Live Demos server that's running on a **m1.small** instance shared with 25 other ASP.NET Web Applications. - -## [AWS Imgur](http://awsapps.servicestack.net/imgur/) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/imgur.png)](http://awsapps.servicestack.net/imgur/) - -### S3VirtualPathProvider - -The backend -[ImageService.cs](https://github.com/ServiceStackApps/AwsApps/blob/master/src/AwsApps/imgur/ImageService.cs) -implementation for AWS Imgur has been rewritten to use the Virtual FileSystem instead of -[accessing the FileSystem directly](https://github.com/ServiceStackApps/Imgur/blob/master/src/Imgur/Global.asax.cs). -The benefits of this approach is that with -[2 lines of configuration](https://github.com/ServiceStackApps/AwsApps/blob/4817f5c6ad69defd74d528403bfdb03e5958b0b3/src/AwsApps/AppHost.cs#L44-L45) -we can have files written to an S3 Bucket instead: - -```csharp -var s3Client = new AmazonS3Client(AwsConfig.AwsAccessKey, AwsConfig.AwsSecretKey, RegionEndpoint.USEast1); -VirtualFiles = new S3VirtualPathProvider(s3Client, AwsConfig.S3BucketName, this); -``` - -If we comment out the above configuration any saved files are instead written to the local FileSystem (default). - -The benefit of using managed S3 File Storage is better scalability as your App Servers can remain stateless, improved -performance as overhead of serving static assets can be offloaded by referencing the S3 Bucket directly and for even -better responsiveness you can connect the S3 bucket to a CDN. - -## [REST Files](http://awsapps.servicestack.net/restfiles/) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/restfiles.png)](http://awsapps.servicestack.net/restfiles/) - -REST Files GitHub-like explorer is another example that was -[rewritten to use ServiceStack's Virtual File System](https://github.com/ServiceStackApps/AwsApps/blob/master/src/AwsApps/restfiles/FilesService.cs) -and now provides remote file management of an S3 Bucket behind a REST-ful API. - -## [AWS Email Contacts](http://awsapps.servicestack.net/emailcontacts/) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/emailcontacts.png)](http://awsapps.servicestack.net/emailcontacts/) - -### SqsMqServer - -The [AWS Email Contacts](http://awsapps.servicestack.net/emailcontacts/) example shows the same long-running -[EmailContact Service](https://github.com/ServiceStackApps/AwsApps/blob/4817f5c6ad69defd74d528403bfdb03e5958b0b3/src/AwsApps/emailcontacts/EmailContactServices.cs#L81) -being executed from both HTTP and MQ Server by just -[changing which url the HTML Form is posted to](https://github.com/ServiceStackApps/AwsApps/blob/4817f5c6ad69defd74d528403bfdb03e5958b0b3/src/AwsApps/emailcontacts/default.cshtml#L203): - -```html -//html -
      - ... -
      - - -
      - ... - -``` - -> The urls are populated from a typed Request DTO using the [Reverse Routing Extension methods](https://github.com/ServiceStack/ServiceStack/wiki/Routing#reverse-routing) - -Checking the **Email via MQ** checkbox fires the JavaScript handler below that's registered as [declarative event in ss-utils.js](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library#declarative-events): - -```js -$(document).bindHandlers({ - toggleAction: function() { - var $form = $(this).closest("form"), action = $form.attr("action"); - $form.attr("action", $form.data("action-alt")) - .data("action-alt", action); - } -}); -``` - -The code to configure and start an SQS MQ Server is similar to [other MQ Servers](https://github.com/ServiceStack/ServiceStack/wiki/Messaging): - -```csharp -container.Register(c => new SqsMqServer( - AwsConfig.AwsAccessKey, AwsConfig.AwsSecretKey, RegionEndpoint.USEast1) { - DisableBuffering = true, // Trade-off latency vs efficiency -}); - -var mqServer = container.Resolve(); -mqServer.RegisterHandler(ExecuteMessage); -mqServer.Start(); -``` - -When an MQ Server is registered, ServiceStack automatically publishes Requests accepted on the "One Way" -[pre-defined route](https://github.com/ServiceStack/ServiceStack/wiki/Routing#pre-defined-routes) -to the registered MQ broker. The message is later picked up and executed by a Message Handler on a background Thread. - -## [AWS Auth](http://awsapps.servicestack.net/awsauth/) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/awsauth.png)](http://awsapps.servicestack.net/awsauth/) - -### DynamoDbAuthRepository - -[AWS Auth](http://awsapps.servicestack.net/awsauth/) -is an example showing how easy it is to enable multiple Auth Providers within the same App which allows Sign-Ins from -Twitter, Facebook, GitHub, Google, Yahoo and LinkedIn OAuth providers, as well as HTTP Basic and Digest Auth and -normal Registered User logins and Custom User Roles validation, all managed in DynamoDB Tables using -the registered `DynamoDbAuthRepository` below: - -```csharp -container.Register(new DynamoDbAuthRepository(db, initSchema:true)); -``` - -Standard registration code is used to configure the `AuthFeature` with all the different Auth Providers AWS Auth wants -to support: - -```csharp -return new AuthFeature(() => new AuthUserSession(), - new IAuthProvider[] - { - new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials - new BasicAuthProvider(), //Sign-in with HTTP Basic Auth - new DigestAuthProvider(AppSettings), //Sign-in with HTTP Digest Auth - new TwitterAuthProvider(AppSettings), //Sign-in with Twitter - new FacebookAuthProvider(AppSettings), //Sign-in with Facebook - new YahooOpenIdOAuthProvider(AppSettings), //Sign-in with Yahoo OpenId - new OpenIdOAuthProvider(AppSettings), //Sign-in with Custom OpenId - new GoogleOAuth2Provider(AppSettings), //Sign-in with Google OAuth2 Provider - new LinkedInOAuth2Provider(AppSettings), //Sign-in with LinkedIn OAuth2 Provider - new GithubAuthProvider(AppSettings), //Sign-in with GitHub OAuth Provider - }) -{ - HtmlRedirect = "/awsauth/", //Redirect back to AWS Auth app after OAuth sign in - IncludeRegistrationService = true, //Include ServiceStack's built-in RegisterService -}; -``` - -### DynamoDbAppSettings - -The AuthFeature looks for the OAuth settings for each AuthProvider in the registered -[AppSettings](https://github.com/ServiceStack/ServiceStack/wiki/AppSettings), which for deployed **Release** builds -gets them from multiple sources. Since `DynamoDbAppSettings` is registered first in a `MultiAppSettings` collection -it checks entries in the DynamoDB `ConfigSetting` Table first before falling back to local -[Web.config appSettings](https://github.com/ServiceStackApps/AwsApps/blob/4817f5c6ad69defd74d528403bfdb03e5958b0b3/src/AwsApps/Web.config#L15): - -```csharp -#if !DEBUG - AppSettings = new MultiAppSettings( - new DynamoDbAppSettings(new PocoDynamo(AwsConfig.CreateAmazonDynamoDb()), initSchema:true), - new AppSettings()); // fallback to Web.confg -#endif -``` - -Storing production config in DynamoDB reduces the effort for maintaining production settings decoupled from source code. -The App Settings were populated in DynamoDB using -[this simple script](https://github.com/ServiceStackApps/AwsApps/blob/9d4d3c3dfbf127ce0890d0984c264e8b440abd3f/src/AwsApps/AdminTasks.cs#L58) -which imports its settings from a local [appsettings.txt file](https://github.com/ServiceStack/ServiceStack/wiki/AppSettings#textfilesettings): - -```csharp -var fileSettings = new TextFileSettings("~/../../deploy/appsettings.txt".MapHostAbsolutePath()); -var dynamoSettings = new DynamoDbAppSettings(AwsConfig.CreatePocoDynamo()); -dynamoSettings.InitSchema(); - -//dynamoSettings.Set("SmtpConfig", "{Username:REPLACE_USER,Password:REPLACE_PASS,Host:AWS_HOST,Port:587}"); -foreach (var config in fileSettings.GetAll()) -{ - dynamoSettings.Set(config.Key, config.Value); -} -``` - -#### ConfigSettings Table in DynamoDB - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/aws-configsettings.png) - -## [AWS Todos](http://awsapps.servicestack.net/todo/) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/apps/screenshots/todos.png)](http://awsapps.servicestack.net/todo/) - -The [Backbone TODO App](http://todomvc.com/examples/backbone/) is a famous minimal example used as a "Hello, World" -example to showcase and compare JavaScript client frameworks. The example also serves as a good illustration of the -clean and minimal code it takes to build a simple CRUD Service utilizing a DynamoDB back-end with the new PocoDynamo client: - -```csharp -public class TodoService : Service -{ - public IPocoDynamo Dynamo { get; set; } - - public object Get(Todo todo) - { - if (todo.Id != default(long)) - return Dynamo.GetItem(todo.Id); - - return Dynamo.GetAll(); - } - - public Todo Post(Todo todo) - { - Dynamo.PutItem(todo); - return todo; - } - - public Todo Put(Todo todo) - { - return Post(todo); - } - - public void Delete(Todo todo) - { - Dynamo.DeleteItem(todo.Id); - } -} -``` - -As it's a clean POCO, the `Todo` model can be also reused as-is throughout ServiceStack in Redis, OrmLite, Caching, Config, DTO's, etc: - -```csharp -public class Todo -{ - [AutoIncrement] - public long Id { get; set; } - public string Content { get; set; } - public int Order { get; set; } - public bool Done { get; set; } -} -``` - -## [PocoDynamo](https://github.com/ServiceStack/PocoDynamo) - -PocoDynamo is a highly productive, feature-rich, typed .NET client which extends -[ServiceStack's Simple POCO life](http://stackoverflow.com/a/32940275/85785) -by enabling re-use of your code-first data models with Amazon's industrial strength and highly-scalable -NoSQL [DynamoDB](https://aws.amazon.com/dynamodb/). - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/aws/pocodynamo/related-customer.png) - -#### First class support for reusable, code-first POCOs - -It works conceptually similar to ServiceStack's other code-first -[OrmLite](https://github.com/ServiceStack/ServiceStack.OrmLite) and -[Redis](https://github.com/ServiceStack/ServiceStack.Redis) clients by providing a high-fidelity, managed client that enhances -AWSSDK's low-level [IAmazonDynamoDB client](http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/UsingAWSsdkForDotNet.html), -with rich, native support for intuitively mapping your re-usable code-first POCO Data models into -[DynamoDB Data Types](http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Types.html). - -### PocoDynamo Features - -#### Advanced idiomatic .NET client - -PocoDynamo provides an idiomatic API that leverages .NET advanced language features with streaming API's returning -`IEnumerable` lazily evaluated responses that transparently performs multi-paged requests behind-the-scenes as the -result set is iterated. It high-level API's provides a clean lightweight adapter to -transparently map between .NET built-in data types and DynamoDB's low-level attribute values. Its efficient batched -API's take advantage of DynamoDB's `BatchWriteItem` and `BatchGetItem` batch operations to perform the minimum number -of requests required to implement each API. - -#### Typed, LINQ provider for Query and Scan Operations - -PocoDynamo also provides rich, typed LINQ-like querying support for constructing DynamoDB Query and Scan operations, -dramatically reducing the effort to query DynamoDB, enhancing readability whilst benefiting from Type safety in .NET. - -#### Declarative Tables and Indexes - -Behind the scenes DynamoDB is built on a dynamic schema which whilst open and flexible, can be cumbersome to work with -directly in typed languages like C#. PocoDynamo bridges the gap and lets your app bind to impl-free and declarative POCO -data models that provide an ideal high-level abstraction for your business logic, hiding a lot of the complexity of -working with DynamoDB - dramatically reducing the code and effort required whilst increasing the readability and -maintainability of your Apps business logic. - -It includes optimal support for defining simple local indexes which only require declaratively annotating properties -to index with an `[Index]` attribute. - -Typed POCO Data Models can be used to define more complex Local and Global DynamoDB Indexes by implementing -`IGlobalIndex` or `ILocalIndex` interfaces which PocoDynamo uses along with the POCOs class structure -to construct Table indexes at the same time it creates the tables. - -In this way the Type is used as a DSL to define DynamoDB indexes where the definition of the index is decoupled from -the imperative code required to create and query it, reducing the effort to create them whilst improving the -visualization and understanding of your DynamoDB architecture which can be inferred at a glance from the POCO's -Type definition. PocoDynamo also includes first-class support for constructing and querying Global and Local Indexes -using a familiar, typed LINQ provider. - -#### Resilient - -Each operation is called within a managed execution which transparently absorbs the variance in cloud services -reliability with automatic retries of temporary errors, using an exponential backoff as recommended by Amazon. - -#### Enhances existing APIs - -PocoDynamo API's are a lightweight layer modeled after DynamoDB API's making it predictable the DynamoDB operations -each API calls under the hood, retaining your existing knowledge investment in DynamoDB. -When more flexibility is needed you can access the low-level `AmazonDynamoDBclient` from the `IPocoDynamo.DynamoDb` -property and talk with it directly. - -Whilst PocoDynamo doesn't save you for needing to learn DynamoDB, its deep integration with .NET and rich support for -POCO's smoothes out the impedance mismatches to enable an type-safe, idiomatic, productive development experience. - -#### High-level features - -PocoDynamo includes its own high-level features to improve the re-usability of your POCO models and the development -experience of working with DynamoDB with support for Auto Incrementing sequences, Query expression builders, -auto escaping and converting of Reserved Words to placeholder values, configurable converters, scoped client -configurations, related items, conventions, aliases, dep-free data annotation attributes and more. - -### Download - -PocoDynamo is contained in ServiceStack's AWS NuGet package: - - PM> Install-Package ServiceStack.Aws - -PocoDynamo has a 10 Tables [free-quota usage](https://servicestack.net/download#free-quotas) limit which is unlocked with a [license key](https://servicestack.net/pricing). - -To get started we'll need to create an instance of `AmazonDynamoDBClient` with your AWS credentials and Region info: - -```csharp -var awsDb = new AmazonDynamoDBClient(AWS_ACCESS_KEY, AWS_SECRET_KEY, RegionEndpoint.USEast1); -``` - -Then to create a PocoDynamo client pass the configured AmazonDynamoDBClient instance above: - -```csharp -var db = new PocoDynamo(awsDb); -``` - -> Clients are Thread-Safe so you can register them as a singleton and share the same instance throughout your App - -### Creating a Table with PocoDynamo - -PocoDynamo enables a declarative code-first approach where it's able to create DynamoDB Table schemas from just your -POCO class definition. Whilst you could call `db.CreateTable()` API and create the Table directly, the recommended -approach is instead to register all the tables your App uses with PocoDynamo on Startup, then just call `InitSchema()` -which will go through and create all missing tables: - -```csharp -//PocoDynamo -var db = new PocoDynamo(awsDb) - .RegisterTable(); - -db.InitSchema(); - -db.GetTableNames().PrintDump(); -``` - -In this way your App ends up in the same state with all tables created if it was started with **no tables**, **all tables** -or only a **partial list** of tables. After the tables are created we query DynamoDB to dump its entire list of Tables, -which if you started with an empty DynamoDB instance would print the single **Todo** table name to the Console: - - [ - Todo - ] - -### Managed DynamoDB Client - -Every request in PocoDynamo is invoked inside a managed execution where any temporary errors are retried using the -[AWS recommended retries exponential backoff](http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html#APIRetries). - -All PocoDynamo API's returning `IEnumerable` returns a lazy evaluated stream which behind-the-scenes sends multiple -paged requests as needed whilst the sequence is being iterated. As LINQ APIs are also lazily evaluated you could use -`Take()` to only download however the exact number results you need. So you can query the first 100 table names with: - -```csharp -//PocoDynamo -var first100TableNames = db.GetTableNames().Take(100).ToList(); -``` - -and PocoDynamo will only make the minimum number of requests required to fetch the first 100 results. - -### PocoDynamo Examples - -#### [DynamoDbCacheClient](https://github.com/ServiceStack/ServiceStack.Aws/blob/master/src/ServiceStack.Aws/DynamoDb/DynamoDbCacheClient.cs) - -We've been quick to benefit from the productivity advantages of PocoDynamo ourselves where we've used it to rewrite -[DynamoDbCacheClient](https://github.com/ServiceStack/ServiceStack.Aws/blob/master/src/ServiceStack.Aws/DynamoDb/DynamoDbCacheClient.cs) -which is now just 2/3 the size and much easier to maintain than the existing -[Community-contributed version](https://github.com/ServiceStack/ServiceStack/blob/22aca105d39997a8ea4c9dc20b242f78e07f36e0/src/ServiceStack.Caching.AwsDynamoDb/DynamoDbCacheClient.cs) -whilst at the same time extending it with even more functionality where it now implements the `ICacheClientExtended` API. - -#### [DynamoDbAuthRepository](https://github.com/ServiceStack/ServiceStack.Aws/blob/master/src/ServiceStack.Aws/DynamoDb/DynamoDbAuthRepository.cs) - -PocoDynamo's code-first Typed API made it much easier to implement value-added DynamoDB functionality like the new -[DynamoDbAuthRepository](https://github.com/ServiceStack/ServiceStack.Aws/blob/master/src/ServiceStack.Aws/DynamoDb/DynamoDbAuthRepository.cs) -which due sharing a similar code-first POCO approach to OrmLite, ended up being a straight-forward port of the existing -[OrmLiteAuthRepository](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Server/Auth/OrmLiteAuthRepository.cs) -where it was able to reuse the existing `UserAuth` and `UserAuthDetails` POCO data models. - -#### [DynamoDbTests](https://github.com/ServiceStack/ServiceStack.Aws/tree/master/tests/ServiceStack.Aws.DynamoDbTests) - -Despite its young age we've added a comprehensive test suite behind PocoDynamo which has become our exclusive client -for developing DynamoDB-powered Apps. - -### [PocoDynamo Docs](https://github.com/ServiceStack/PocoDynamo) - -This only scratches the surface of what PocoDynamo can do, comprehensive documentation is available in the -[PocoDynamo project](https://github.com/ServiceStack/PocoDynamo) explaining how it compares to DynamoDB's AWSSDK client, -how to use it to store related data, how to query indexes and how to use its rich LINQ querying functionality to query -DynamoDB. - -## [Getting started with AWS + ServiceStack Guides](https://github.com/ServiceStackApps/AwsGettingStarted) - -Amazon offers managed hosting for a number of RDBMS and Caching servers which ServiceStack provides first-class -clients for. We've provided a number of guides to walk through setting up these services from your AWS account -and connect to them with ServiceStack's typed .NET clients. - -### [AWS RDS PostgreSQL and OrmLite](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/postgres-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/rds-postgres-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/postgres-guide.md) - -### [AWS RDS Aurora and OrmLite](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/aurora-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/rds-aurora-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/aurora-guide.md) - -### [AWS RDS MySQL and OrmLite](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/mssql-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/rds-mysql-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/mssql-guide.md) - -### [AWS RDS MariaDB and OrmLite](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/mariadb-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/rds-mariadb-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/mariadb-guide.md) - -### [AWS RDS SQL Server and OrmLite](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/mssql-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/rds-sqlserver-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/mssql-guide.md) - -### [AWS ElastiCache Redis and ServiceStack](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/redis-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/elasticache-redis-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/redis-guide.md) - -### [AWS ElastiCache Redis and ServiceStack](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/memcached-guide.md) - -[![](https://github.com/ServiceStack/Assets/raw/master/img/aws/elasticache-memcached-powered-by-aws.png)](https://github.com/ServiceStackApps/AwsGettingStarted/blob/master/docs/memcached-guide.md) - -The source code used in each guide is also available in the [AwsGettingStarted](https://github.com/ServiceStackApps/AwsGettingStarted) repo. - -# Community - -We're excited to learn that [Andreas Niedermair](https://twitter.com/dittodhole) new ServiceStack book is now available! - -## [Mastering ServiceStack](https://www.packtpub.com/application-development/mastering-servicestack) by [Andreas Niedermair](https://twitter.com/dittodhole) - -[](https://www.packtpub.com/application-development/mastering-servicestack) - -Mastering ServiceStack covers real-life problems that occur over the lifetime of a distributed system and how to -solve them by deeply understanding the tools of ServiceStack. Distributed systems is the enterprise solution that -provide flexibility, reliability, scaling, and performance. ServiceStack is an outstanding tool belt to create such a -system in a frictionless manner, especially sophisticated designed and fun to use. - -The book starts with an introduction covering the essentials, but assumes you are just refreshing, are a very fast -learner, or are an expert in building web services. Then, the book explains ServiceStack's data transfer object patterns -and teach you how it differs from other methods of building web services with different protocols, such as SOAP and SOA. -It also introduces more low-level details such as how to extend the User Auth, message queues and concepts on how the -technology works. - -By the end of this book, you will understand the concepts, framework, issues, and resolutions related to ServiceStack. - -## [TypeScript](https://github.com/ServiceStack/ServiceStack/wiki/TypeScript-Add-ServiceStack-Reference) - -![ServiceStack and TypeScript Banner](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/wikis/typescript-banner.png) - -We've extended our existing TypeScript support for generating interface definitions for your DTO's with the much requested -`ExportAsTypes=true` option which instead generates non-ambient concrete TypeScript Types. This option is enabled at the -new `/types/typescript` route so you can get both concrete types and interface defintions at: - - - [/types/typescript](http://test.servicestack.net/types/typescript) - for generating concrete module and classes - - [/types/typescript.d](http://test.servicestack.net/types/typescript.d) - for generating ambient interface definitions - -### Auto hyper-linked default HTML5 Pages - -Any urls strings contained in default HTML5 Report Pages are automatically converted to a hyperlinks. -We can see this in the new `/types` route which returns links to all different -[Add ServiceStack Reference supported languages](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference#supported-languages): - -```csharp -public object Any(TypeLinks request) -{ - var response = new TypeLinksResponse - { - Metadata = new TypesMetadata().ToAbsoluteUri(), - Csharp = new TypesCSharp().ToAbsoluteUri(), - Fsharp = new TypesFSharp().ToAbsoluteUri(), - VbNet = new TypesVbNet().ToAbsoluteUri(), - TypeScript = new TypesTypeScript().ToAbsoluteUri(), - TypeScriptDefinition = new TypesTypeScriptDefinition().ToAbsoluteUri(), - Swift = new TypesSwift().ToAbsoluteUri(), - Java = new TypesJava().ToAbsoluteUri(), - }; - return response; -} -``` - -Where any url returned are now converted into navigatable hyper links, e.g: http://test.servicestack.net/types - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/typelinks.png)](http://test.servicestack.net/types) - -## New License Key Registration Option - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/servicestack-license-env-var.png) - -To simplify license key registration when developing and maintaining multiple ServiceStack solutions we've added a new -option where you can now just register your License Key once in `SERVICESTACK_LICENSE` Environment Variable. -This lets you set it in one location on your local dev workstations and any CI and deployment Servers which then lets -you freely create multiple ServiceStack solutions without having to register the license key with each project. - -> Note: you'll need to restart IIS or VS.NET to have them pickup the new Environment Variable. - -## [Virtual File System](https://github.com/ServiceStack/ServiceStack/wiki/Virtual-file-system) - -ServiceStack's -[Virtual File System](https://github.com/ServiceStack/ServiceStack/wiki/Virtual-file-system) -provides a clean abstraction over file-systems enabling the flexibility to elegantly support a wide range of cascading -file sources. We've extended this functionality even further in this release with a new read/write API that's -now implemented in supported providers: - -```csharp -public interface IVirtualFiles : IVirtualPathProvider -{ - void WriteFile(string filePath, string textContents); - void WriteFile(string filePath, Stream stream); - void WriteFiles(IEnumerable files, Func toPath = null); - void DeleteFile(string filePath); - void DeleteFiles(IEnumerable filePaths); - void DeleteFolder(string dirPath); -} -``` - -> Folders are implicitly created when writing a file to folders that don't exist - -The new `IVirtualFiles` API is available in local FileSystem, In Memory and S3 Virtual path providers: - - - FileSystemVirtualPathProvider - - InMemoryVirtualPathProvider - - S3VirtualPathProvider - -Whilst other read-only `IVirtualPathProvider` include: - - - ResourceVirtualPathProvider - .NET Embedded resources - - MultiVirtualPathProvider - Combination of multiple cascading Virtual Path Providers - -All `IVirtualFiles` providers share the same -[VirtualPathProviderTests](https://github.com/ServiceStack/ServiceStack.Aws/blob/master/tests/ServiceStack.Aws.Tests/S3/VirtualPathProviderTests.cs) -ensuring a consistent behavior where it's now possible to swap between different file storage backends with simple -configuration as seen in the [Imgur](#imgur) and [REST Files](#restfiles) examples. - -### VirtualFiles vs VirtualFileSources - -As typically when saving uploaded files you'd only want files written to a single explicit File Storage provider, -ServiceStack keeps a distinction between the existing read-only Virtual File Sources it uses internally whenever a -static file is requested and the new `IVirtualFiles` which is maintained in a separate `VirtualFiles` property on -`IAppHost` and `Service` base class for easy accessibility: - -```csharp -public class IAppHost -{ - // Read/Write Virtual FileSystem. Defaults to Local FileSystem. - IVirtualFiles VirtualFiles { get; set; } - - // Cascading number of file sources, inc. Embedded Resources, File System, In Memory, S3. - IVirtualPathProvider VirtualFileSources { get; set; } -} - -public class Service : IService //ServiceStack's convenient concrete base class -{ - //... - public IVirtualPathProvider VirtualFiles { get; } - public IVirtualPathProvider VirtualFileSources { get; } -} -``` - -Internally ServiceStack only uses `VirtualFileSources` itself to serve static file requests. -The new `IVirtualFiles` is a clean abstraction your Services can bind to when saving uploaded files which can be easily -substituted when you want to change file storage backends. If not specified, `VirtualFiles` defaults to your local -filesystem at your host project's root directory. - -### Changes - -To provide clear and predictable naming. some of the existing APIs were deprecated in favor of the new nomenclature: - - - `IAppHost.VirtualPathProvider` deprecated, renamed to `IAppHost.VirtualFileSources` - - `IAppHost.GetVirtualPathProviders()` deprecated, renamed to `IAppHost.GetVirtualFileSources()` - - `IWriteableVirtualPathProvider` deprecated, renamed to `IVirtualFiles` - - `IWriteableVirtualPathProvider.AddFile()` deprecated, renamed to `WriteFile()` - - `VirtualPath` no longer returns paths prefixed with `/` and VirtualPath of a Root directory is `null` - This affects `Config.ScanSkipPaths` which should no longer start with `/`, e.g: "node_modules/", "bin/", "obj/" - -These old API's have been marked `[Obsolete]` and will be removed in a future version. -If you're using them, please upgrade to the newer APIs. - -## HttpResult - -### Custom Serialized Responses - -The new `IHttpResult.ResultScope` API provides an opportunity to execute serialization within a custom scope, e.g. this can -be used to customize the serialized response of adhoc services that's different from the default global configuration with: - -```csharp -return new HttpResult(dto) { - ResultScope = () => JsConfig.With(includeNullValues:true) -}; -``` - -Which enables custom serialization behavior by performing the serialization within the custom scope, equivalent to: - -```csharp -using (JsConfig.With(includeNullValues:true)) -{ - var customSerializedResponse = Serialize(dto); -} -``` - -### Cookies - -New cookies can be added to HttpResult’s new `IHttpResult.Cookies` collection. - -### VirtualFile downloads - -The a new constructor overload lets you return a `IVirtualFile` download with: - -```csharp -return new HttpResult(VirtualFiles.GetFile(targetPath), asAttachment: true); -``` - -### HttpError changes - -The `HttpError` constructor that accepts a `HttpStatusCode` and a custom string description, e.g: - -```csharp -return new HttpError(HttpStatusCode.NotFound, "Custom Description"); -return HttpError.NotFound("Custom Description"); -``` - -Now returns the `HttpStatusCode` string as the ErrorCode instead of duplicating the error message, -so now the populated `ResponseStatus` for the above custom HttpError returns: - -```csharp -ResponseStatus { - ErrorCode = "NotFound", // previous: Custom Description - Message = "Custom Description" -} -``` - -## [AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query) - -We've added a new `%!` and `%NotEqualTo` implicit query convention which is now available on all Auto queries: - - /rockstars?age!=27 - /rockstars?AgeNotEqualTo=27 - -## Razor - -New API's for explicitly refreshing a page: - - HostContext.GetPlugin().RefreshPage(file.VirtualPath); - -Also available in Markdown Format: - - HostContext.GetPlugin().RefreshPage(file.VirtualPath); - -New Error API's in base Razor Views for inspecting error responses: - - - `GetErrorStatus()` - get populated Error `ResponseStatus` - - `GetErrorHtml()` - get error info marked up in a structured html fragment - -Both API's return `null` if there were no errors. - -### Improved support for Xamarin.Mac - -The ServiceStack.Client PCL provider for Xamarin.Mac now has an explicit reference **Xamarin.Mac.dll** which allows it -to work in projects with the **Link SDK Assemblies Only**. - -## Redis - -Allow `StoreAsHash` behavior converting a POCO object into a string Dictionary to be overridden to control how POCOs -are stored in a Redis Hash type, e.g: - -```csharp -RedisClient.ConvertToHashFn = o => -{ - var map = new Dictionary(); - o.ToObjectDictionary().Each(x => map[x.Key] = (x.Value ?? "").ToJsv()); - return map; -}; - -Redis.StoreAsHash(dto); //Uses above implementation -``` - -## RedisReact Browser Updates - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/order.png) - -We've continued to add enhancements to Redis React Browser based on your feedback: - -### Delete Actions - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/updates/delete-actions.png) - -Delete links added on each key. Use the **delete** link to delete a single key or the **all** link to delete all -related keys currently being displayed. - -### Expanded Prompt - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/updates/expanded-prompt.png) - -Keys can now be edited in a larger text area which uses the full height of the screen real-estate available - -this is now the default view for editing a key. Click the collapse icon when finished to return to the -console for execution. - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/updates/expand-prompt.png) - -All Redis Console commands are now be edited in the expanded text area by clicking on the Expand icon -on the right of the console. - -### Clear Search - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/updates/clear-search.png) - -Use the **X** icon in the search box to quickly clear the current search. - -## OrmLite - -### System Variables and Default Values - -To provide richer support for non-standard default values, each RDBMS Dialect Provider now contains a -`OrmLiteDialectProvider.Variables` placeholder dictionary for storing common, but non-standard RDBMS functionality. -We can use this to declaratively define non-standard default values that works across all supported RDBMS's -like automatically populating a column with the RDBMS UTC Date when Inserted with a `default(T)` Value: - -```csharp -public class Poco -{ - [Default(OrmLiteVariables.SystemUtc)] //= {SYSTEM_UTC} - public DateTime CreatedTimeUtc { get; set; } -} -``` - -OrmLite variables need to be surrounded with `{}` braces to identify that it's a placeholder variable, e.g `{SYSTEM_UTC}`. - -### Parameterized SqlExpressions - -Preview of a new parameterized SqlExpression provider that's now available for SQL Server and Oracle, opt-in with: - -```csharp -OrmLiteConfig.UseParameterizeSqlExpressions = true; -``` - -When enabled, OrmLite instead uses Typed SQL Expressions inheriting from `ParameterizedSqlExpression` to convert -most LINQ expression arguments into parameterized variables instead of inline SQL Literals for improved RDBMS query -profiling and performance. Note: this is a beta feature that's subject to change. - -### Custom Load References - -[Johann Klemmack](https://github.com/jklemmack) added support for selectively specifying which references you want to load, e.g: - -```csharp -var customerWithAddress = db.LoadSingleById(customer.Id, include: new[] { "PrimaryAddress" }); - -//Alternative -var customerWithAddress = db.LoadSingleById(customer.Id, include: x => new { x.PrimaryAddress }); -``` - -### T4 Templates - -OrmLite's T4 templates for generating POCO types from an existing database schema has improved support for generating -stored procedures thanks to [Richard Safier](https://github.com/rsafier). - -## ServiceStack.Text - -The new `ConvertTo` on `JsonObject` helps dynamically parsing JSON into typed object, e.g. you can dynamically -parse the following OData json response: - -```json -{ - "odata.metadata":"...", - "value":[ - { - "odata.id":"...", - "QuotaPolicy@odata.navigationLinkUrl":"...", - "#SetQuotaPolicyFromLevel": { "target":"..." }, - "Id":"1111", - "UserName":"testuser", - "DisplayName":"testuser Large", - "Email":"testuser@testuser.ca" - } - ] -} -``` - -By navigating down a JSON object graph with `JsonObject` then using `ConvertTo` to convert a unstructured JSON object -into a concrete POCO Type, e.g: - -```csharp -var users = JsonObject.Parse(json) - .ArrayObjects("value") - .Map(x => x.ConvertTo()); - -``` - -## Minor Features - -- Server Events `/event-subscribers` route now returns all channel subscribers -- **PATCH** method is allowed in CORS Feature by default -- Swagger Summary for all servies under a particular route can be specified in `SwaggerFeature.RouteSummary` Dictionary -- New requested `FacebookAuthProvider.Fields` can be customized with `oauth.facebook.Fields` -- Added Swift support for `TreatTypesAsStrings` for returning specific .NET Types as Strings -- New `IAppSettings.GetAll()` added on all [AppSetting](https://github.com/ServiceStack/ServiceStack/wiki/AppSettings) sources fetches all App config in a single call -- [ServiceStackVS](https://github.com/ServiceStack/ServiceStackVS) updated with ATS exception for React Desktop OSX Apps -- External NuGet packages updated to their latest stable version - -## New Signed Packages - - - ServiceStack.Mvc.Signed - - ServiceStack.Authentication.OAuth2.Signed - -## v4.0.48 Issues - -### TypeScript missing BaseUrl - -The TypeScript Add ServiceStack Reference feature was missing the BaseUrl in header comments preventing updates. It's now been resolved -[from this commit](https://github.com/ServiceStack/ServiceStack/commit/10728d1e746b0bf2f84e081eb6319d88ae974677) that's now -available in our [pre-release v4.0.49 MyGet packages](https://github.com/ServiceStack/ServiceStack/wiki/MyGet). - -### ServiceStack.Mvc incorrectly references ServiceStack.Signed - -The **ServiceStack.Mvc** project had a invalid dependency on **ServiceStack.Signed** which has been resolved -[from this commit](https://github.com/ServiceStack/ServiceStack/commit/2f0946e8cb755103082de24949e35fc70f9f72ae) that's now -available in our [pre-release v4.0.49 MyGet packages](https://github.com/ServiceStack/ServiceStack/wiki/MyGet). - -You can workaround this by manually removing the **ServiceStack.Signed** packages and adding the **ServiceStack** packages instead. - -### Config.ScanSkipPaths not ignoring folders - -The change of removing `/` prefixes from Virtual Paths meant folders ignored in `Config.ScanSkipPaths` were no -longer being ignored. It's important node.js-based Single Page App templates ignore `node_modules/` since trying -to scan it throws an error on StartUp when it reaches paths greater than Windows **260 char limit**. This is -fixed in the [pre-release v4.0.49 MyGet packages](https://github.com/ServiceStack/ServiceStack/wiki/MyGet). - -You can also work around this issue in v4.0.48 by removing the prefix from `Config.ScanSkipPaths` folders -in `AppHost.Configure()` manually with: - -```csharp -SetConfig(new HostConfig { ... }); - -for (int i = 0; i < Config.ScanSkipPaths.Count; i++) -{ - Config.ScanSkipPaths[i] = Config.ScanSkipPaths[i].TrimStart('/'); -} -``` - -# v4.0.46 Release Notes - -## [React Desktop Apps!](https://github.com/ServiceStackApps/ReactDesktopApps) - -We're super excited to announce React Desktop Apps which lets you re-use your Web Development skills to develop multi-platform -Desktop Apps with React, ServiceStack and .NET. - -React Desktop Apps take advantage of the adaptability, navigation and deep-linking benefits of a Web-based UI, the productivity -and responsiveness of the [React framework](https://facebook.github.io/react/), -the performance, rich features and functionality contained in -[ServiceStack](https://github.com/ServiceStack/ServiceStack/wiki) and the .NET Framework combined with the native experience and -OS Integration possible from a Native Desktop App - all within a single VS .NET template! - -![React Desktop Apps](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/gap/react-desktop-splash.png) - -The new **React Desktop Apps** template in -[ServiceStackVS](https://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) -provides everything you need to package your **ServiceStack ASP.NET Web App** into a native Windows **Winforms App**, -an OSX **Cocoa App** or cross-platform **Windows/OSX/Linux Console App** which instead of being -embedded inside a Native UI, runs "headless" and launches the User's prefered Web Browser for its Web UI. - -This Hybrid model of developing Desktop Apps with modern WebKit technologies offers a more productive and reusable alternative -with greater development effort ROI than existing bespoke WPF Apps in XAML or Cocoa OSX Apps with Xcode. -It enables full code reuse of your Web App whilst still allowing for platform specific .js, .css and C# specialization when needed. -These advantages are also why GitHub also adopted a similar approach for their new cross-platform UI in their flagship -[Windows and OSX Desktop Apps](http://githubengineering.com/cross-platform-ui-in-github-desktop/). - -### Single Installer-less Executable - -Each application is compiled into a **single xcopy-able executable** that's runnable directly without a -Software install. The only pre-requisite is the .NET 4.5 Framework on Windows -(pre-installed on recent versions) or -[Mono for Linux](http://www.mono-project.com/docs/getting-started/install/linux/). -The OSX Cocoa [Xamarin.Mac](https://xamarin.com/mac) App has the option to bundle the Mono runtime alleviating the need for -users to have an existing install of Mono. - -The default template includes **ServiceStack.Server** NuGet packages which includes all of ServiceStack as well as -Redis, OrmLite and other high-level functionality depending on OrmLite and Redis including -[AutoQuery](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query), -[Redis Server Events](https://github.com/ServiceStack/ServiceStack/wiki/Redis-Server-Events), -[Redis MQ](https://github.com/ServiceStack/ServiceStack/wiki/Messaging-and-Redis), -etc. Despite its features, ServiceStack is super lean where the working Empty Template Console App project which includes -jQuery, Bootstrap, React and its CSS, JS and Font resources compiles down into a single .NET .exe that only weighs -**1.5 MB** zipped or **4.7 MB** uncompressed. - -### [Modern Web Application Development](https://github.com/ServiceStackApps/ReactDesktopApps#react-web-development) - -The React Desktop Template is structured for optimal developer productivity, fast iterations, maximum re-use, -easy customizability and optimal runtime performance that's driven by a pre-configured automated workflow. -It also maximizes skill re-use where most development time will be spent developing a normal ASP.NET -React Web Application without any consideration for the different platforms the tooling creates. - -The template follows the same -[Modern React Apps with .NET](https://github.com/ServiceStackApps/Chat-React#modern-reactjs-apps-with-net) -as ServiceStack's other Single Page App templates which uses node's rich npm ecosystem to enable access to its premier -Web technologies including [bower](http://bower.io/) for client dependencies and pre-configured -[Grunt](http://gruntjs.com) and [Gulp](http://gulpjs.com) tasks to take care of website bundling, optimization, -application packaging and ASP.NET Website deployemnts. - -The entire React application is hosted within a single static -[default.html](https://github.com/ServiceStackApps/ReactDesktopApps/blob/master/src/DefaultApp/DefaultApp/DefaultApp/default.html) -which is itself only used to structure the websites resources into logical groups where 3rd Party -JavaScript libraries and CSS are kept isolated from your own Application's source code. The groups are defined -by HTML comments which instruct -[Gulps userref](https://www.npmjs.com/package/gulp-useref) plugin on how to minify and optimize your -Apps resources. - -### React Desktop App VS.NET Template - -The **React Desktop Apps** template is pre-configured with the necessary tools to package your Web Application -into multiple platforms using the provided Grunt build tasks. The Desktop Apps are also debuggable -allowing for a simplified and iterative dev workflow by running any of the Host Projects: - -- **Web** - ASP.NET Web Application -- **Windows** - Native Windows application embedded in a CefSharp Chromium browser -- **OSX** - Native OS X Cocoa App embedded in a WebView control (requires Xamarin.Mac) -- **Console** - Single portable, cross platform executable that launches the user's prefered browser - -## Project Structure - -The resulting project structure is the same as the -[React App](https://github.com/ServiceStackApps/Chat-React#modern-reactjs-apps-with-net) VS.NET Template, -but with 3 additional projects for hosting the new Desktop and Console Apps and a Common **Resources** project -shared by Host projects containing all the ASP.NET resources (e.g. .css, .js, images, etc) as embedded -resources. - -It's kept in-sync with the primary **DefaultApp** project with the `01-bundle-all` (or `default`) Grunt task. - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/react-desktop-apps/combined-project-structure.png) - -### DefaultApp.sln - -- **DefaultApp** - Complete Web application, inc. all Web App's .js, .css, images, etc. -- **DefaultApp.AppConsole** - Console Host Project -- **DefaultApp.AppWinForms** - WinForms Host Project -- **DefaultApp.Resources** - Shared Embedded resources sourced from **DefaultApp** -- **DefaultApp.ServiceInterface** - ServiceStack Service Implementations -- **DefaultApp.ServiceModel** - Request and Response DTO's -- **DefaultApp.Tests** - NUnit tests - -### DefaultAppMac.sln - - - **DefaultApp.AppMac** - OSX Cocoa Host project - -This is a Xamarin Studio project which can be built with Xamarin.Mac and uses the compiled embedded resources -`lib\DefaultApp.Resources.dll` created by the **01-bundle-all** Grunt task. - -### DefaultApp Project - -The primary **DefaultApp** project contains the complete React Web App hosted in an ASP.NET Project. -It includes `gruntfile.js` which provides the necessary Grunt tasks to bundle and optimize the Wep Application -ready for deployment as well as Grunt tasks to minify the Web Applications assets and publishes them -embedded resources into the shared **DefaultApp.Resources** project. This project is how the React WebApp -is made available to the alternative Desktop and Console Apps. - -The primary Grunt Tasks you'll use to package and deploy your App are contained in **Alias Tasks** group -which is easily runnable from VS .NET's -[Task Runner Explorer](https://visualstudiogallery.msdn.microsoft.com/8e1b4368-4afb-467a-bc13-9650572db708) -which is built into VS 2015: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/gap/react-desktop-tasks.png) - -- **default** - Runs `01-bundle-all` and creates packages for `02-package-console` and `03-package-winforms` -- [**01-bundle-all**](#01-bundle-all) - optimizes and packages Web App the into `wwwroot` and `Resources` project -- [**02-package-console**](#02-package-console) - Packages the Console App in `wwwroot_build\apps` -- [**03-package-winforms**](#03-package-winforms) - Packages the Winforms App in `wwwroot_build\apps` -- [**04-deploy-webapp**](#04-deploy-webapp) - deploys the Web App in `wwwroot` with MS WebDeploy to any IIS Server using config `wwwroot_build\publish\config.json` - -The template also includes the **ILMerge** tool to merge all .NET .dlls (inc. Resources.dll) into a single, -cross-platform Console Application .exe that's runnable as-is on any Windows, OSX or Linux server with .NET -or Mono pre-installed. - -### [Incredible Reuse and Highly Customizable](https://github.com/ServiceStackApps/ReactDesktopApps#host-projects) - -Customizations for each platform is available by modifying the individual `platform.css` and `project.js` files at the -base of each Host folder for adding unique platform-specific JavaScript or CSS. - -In addition, an easy way to limit which HTML elements are displayed is to use the `platform` class to initially -hide the element, then specify which platforms it should be displayed in by listing the specific platforms, e.g: - -```html - -``` - -In this example the **About** link is shown on every platform, **Toggle Window** is specific to Windows and **Close** is available -in both Winforms or OSX Cocoa Desktop Applications. - -Since each host is just a normal C# project you also have complete freedom in enhancing each platform with specific functionality -native to that platform. E.g. you can add 3rd party dependencies or create Services that are only available to that platform. - -### Downloads for the DefaultApp VS.NET Template - -Windows Winforms App: - -#### [DefaultApp-winforms.exe](https://github.com/ServiceStackApps/ReactDesktopApps/raw/master/dist/DefaultApp-winforms.exe) (23.7 MB) - -OSX Cocoa App: - -#### [DefaultApp.AppMac.app.zip](https://github.com/ServiceStackApps/ReactDesktopApps/raw/master/dist/DefaultApp.AppMac.app.zip) (4.1 MB) - -Console App (Windows/OSX/Linux): - -#### [DefaultApp-console.exe](https://github.com/ServiceStackApps/ReactDesktopApps/raw/master/dist/DefaultApp-console.exe) (4.8 MB) or [DefaultApp-console.zip](https://github.com/ServiceStackApps/ReactDesktopApps/raw/master/dist/DefaultApp-console.zip) (1.5 MB) - -## [React Chat Desktop App](https://github.com/ServiceStackApps/ReactChatApps) - -To illustrate the potential of React Desktop Apps we've developed a couple of Basic Examples to show how quick and easy it is -to create highly-interactive Desktop Applications for every major Operating System. - -![WinForms application with loading splash screen](https://github.com/ServiceStack/Assets/raw/master/img/livedemos/react-desktop-apps/redis-chat-app.gif) - -React Chat shows the features and interactivity possible when you have all of ServiceStack available in a Desktop App. React Chat uses -[Server Events](https://github.com/ServiceStack/ServiceStack/wiki/Server-Events) for its real-time notifications allowing ServiceStack -Services to notify the client of events instantly. In React Chat each command is sent by Ajax to a normal ServiceStack Service which -effectively just relays it back to the client via a Server Event. - -After the Server Event reaches the client it calls the registered JavaScript handler, which in the case of `/cmd.toggleFormBorder` calls -[nativeHost.toggleFormBorder()](https://github.com/ServiceStackApps/ReactChatApps/blob/master/src/ReactChat/ReactChat/js/components/ChatApp.jsx#L65). - -In Winforms, nativeHost is registered a C# object courtesy of -[CefSharp's JavaScript Interop](https://github.com/ServiceStackApps/ReactDesktopApps#winforms-native-host) -feature where JavaScript can call C# directly, which for ToggleFormBorder() just toggles the Window's Chrome on/off: - -```csharp -ChromiumBrowser.RegisterJsObject("nativeHost", new NativeHost(this)); - -public class NativeHost -{ - //... - public void ToggleFormBorder() - { - formMain.InvokeOnUiThreadIfRequired(() => { - formMain.FormBorderStyle = formMain.FormBorderStyle == FormBorderStyle.None - ? FormBorderStyle.Sizable - : FormBorderStyle.None; - }); - } -} -``` - -This is also an example of a Windows only feature that only appears when the React Web App hosted in Winforms. - -### Controlling multiple Windows with Server Events - -A nice benefit for using Server Events for real-time communication with JavaScript is that you're able -to control multiple window clients naturally just by having each Windows Application subscribe to the same -remote `/event-stream` url. You can do in React Chat just by opening multiple windows as all subesquent -Windows Apps opened listen to the self-hosting listener of the first one that was opened. - -The `/windows.dance` chat message provides a nice demonstration of this in action :) - -#### [YouTube Live Demo](https://youtu.be/-9kVqdPbqOM) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/react-desktop-apps/dancing-windows.png)](https://youtu.be/-9kVqdPbqOM) - -> In addition to the Default template, ReactChat also has Razor enabled to also generate dynamic server pages - -You can play around with React Chat with the download for your Operating System below: - -### Downloads for the React Chat - -Windows Winforms App: - -#### [ReactChat-winforms.exe](https://github.com/ServiceStackApps/ReactChatApps/raw/master/dist/ReactChat-winforms.exe) (23.6 MB) - -OSX Cocoa App: - -#### [ReactChat.AppMac.mono.app.zip](https://github.com/ServiceStackApps/ReactChatApps/raw/master/dist/ReactChat.AppMac.mono.app.zip) (16.9 MB) or without Mono [ReactChat.AppMac.app.zip](https://github.com/ServiceStackApps/ReactChatApps/raw/master/dist/ReactChat.AppMac.app.zip) (4.51 MB) - -Console App (Windows/OSX/Linux): - -#### [ReactChat-console.exe](https://github.com/ServiceStackApps/ReactChatApps/raw/master/dist/ReactChat-console.exe) (5.33 MB) or [DefaultApp-console.zip](https://github.com/ServiceStackApps/ReactChatApps/raw/master/dist/ReactChatApps-console.zip) (1.93MB) - -## [Introducing Redis React!](https://github.com/ServiceStackApps/RedisReact) - -We're also excited to announce Redis React, which we believe is a good example showing an ideal use-case for React Desktop Apps: - -Redis React is a simple user-friendly UI for browsing data in Redis servers that leverages the navigation and deep-linking -benefits of a Web-based UI, the productivity and responsiveness of the [React framework](http://facebook.github.io/react/) -and the deep Integration possible from a Native App. - -## [Live Demo](http://redisreact.servicestack.net/#/) - -The Redis React App has been packaged for multiple platforms inc. the ASP.NET Live Demo -[redisreact.servicestack.net](http://redisreact.servicestack.net/#/) deployed on AWS which you can use to preview Redis React -browsing a redis server populated with the -[Northwind Dataset](http://northwind.servicestack.net/) persisted as JSON following the -[Complex Type Conventions](http://stackoverflow.com/a/8919931/85785) built into the -[C# ServiceStack.Redis Client](https://github.com/ServiceStack/ServiceStack.Redis). - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/home.png)](http://redisreact.servicestack.net/#/) - -## Download - -Use Redis React to browse your internal Redis Server by downloading the appropriate download for your platform: - -### Windows - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/download-windows10.png)](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact-winforms.exe) - -To run on Windows, download the self-extracting Winforms App: - -#### [RedisReact-winforms.exe](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact-winforms.exe) (23.9MB) - -> Windows requires .NET 4.5 installed which is pre-installed on recent version of Windows - -### OSX - -To run on OSX, download the Cocoa OSX App: - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/download-osx.png)](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact.AppMac.app.zip) - -#### [RedisReact.AppMac.mono.app.zip](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact.AppMac.mono.app.zip) (16.5 MB) or without mono [RedisReact.AppMac.app.zip](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact.AppMac.app.zip) (4.1 MB) - -> The Cocoa OSX App was built with [Xamarin.Mac](https://developer.xamarin.com/guides/mac/getting_started/hello,_mac/) -and includes an embedded version of Mono which doesn't require an existing install of Mono - -### Linux - -To run on Linux, download the cross-platform Console App: - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/download-linux.png)](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact-console.exe) - -#### [RedisReact-console.exe](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact-console.exe) (5.4MB) or [RedisReact-console.exe.zip](https://github.com/ServiceStackApps/RedisReact/raw/master/dist/RedisReact-console.exe.zip) (1.7MB) - -**RedisReact-console.exe** is a headless Console Application that can run on Windows, OSX and Linux -platforms with .NET or Mono installed. - -See the instructions for [Installing Mono on Linux](http://www.mono-project.com/docs/getting-started/install/linux/). -If installing via apt-get, it needs the **mono-complete** package to run. - -### Rich support for JSON - -Redis React is especially useful for browsing JSON values which includes a -[human friendly view of JSON data](#category-item) and the ability to view multiple related keys together -in a [tabular data grid](#view-as-grid) enabling fast inspection of redis data. - -At anytime you can click on the JSON preview to reveal the raw JSON string, or use the Global `t` -shortcut key to toggle between preview mode and raw mode of JSON data. - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/order.png)](http://redisreact.servicestack.net/#/keys?id=urn%3Aorder%3A10860&type=string) - -It also takes advantages of the POCO conventions built into the -[C# ServiceStack.Redis Client](https://github.com/ServiceStack/ServiceStack.Redis) where it will -automatically display any related entities for the current value, as seen with the related -**Customer** the **Order** was for and the **Employee** who created it. - -It works by scanning the JSON fields for names ending with **Id** then taking the prefix and using -it to predict the referenced key, e.g: - - CustomerId:FRANR => urn:customer:FRANR - -It then fetches all the values with the calculated key and displays them below the selected Order. -Clicking the **Customer** or **Employee** Key will navigate to that record, providing nice navigation -for quickly viewing a record and its related entities. - -## [View as Grid](http://redisreact.servicestack.net/#/search?q=urn%3Acategory) - -When keys share the same schema, clicking on the **view as grid** link lets you see multiple search results -displayed in a tabular data grid, e.g: - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/category-grid.png)](http://redisreact.servicestack.net/#/search?q=urn%3Acategory) - -## [Web Console](http://redisreact.servicestack.net/#/console) - -The built-in Console takes advantage of a Web Based UI to provide some nice enhancements. E.g. each -command is displayed on top of the result it returns, where clicking the command populates the text box -making it easy to execute or modify existing commands. Any **OK** Success responses are in green, whilst -any error responses are in red. Also just like JSON values above, it shows a human-friendly view for -JSON data which can be clicked to toggle on/off individually: - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/livedemos/redis-react/console.png)](http://redisreact.servicestack.net/#/console) - -Redis React is packed with a number of other features, checkout the -[project home page](https://github.com/ServiceStackApps/RedisReact) for an Overview and try it out today! - -## [Swift 2.0 Support!](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference) - -We're also happy to announce support for the new and much improved -[Swift 2.0](https://developer.apple.com/swift/) that's now shipping in -[Xcode 7](https://developer.apple.com/xcode/download/) which is now available as a free download for everyone to enjoy. - -![Swift iOS, XCode and OSX Banner](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/swift-logo-banner.jpg) - -We're happy to report that Swift has improved substantially and has also had a positive impact on our Swift Client library, -e.g. Error Handling is more familiar thanks to -[Swift 2.0 new Error Handling](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html) -utilizing a `do/try/catch` block where you can now access ServiceStack Service Exceptions inside a catch block, e.g: - -```swift -let client = JsonServiceClient(baseUrl: "http://test.servicestack.net") - -let request = ThrowValidation() -request.email = "invalidemail" - -do { - let response = try client.post(request) -} catch let responseError as NSError { - - let status:ResponseStatus = responseError.convertUserInfo()! - status.errors.count //= 3 - - status.errors[0].errorCode! //= InclusiveBetween - status.errors[0].fieldName! //= Age - status.errors[0].message! //= 'Age' must be between 1 and 120. You entered 0. -} -``` - -The addition of the new `catch` keyword means the the previous Async promise error handling has now been renamed to `error` -which now looks like: - -```swift -let request = ThrowValidation() -request.email = "invalidemail" - -client.postAsync(request) - .error { responseError in - let status:ResponseStatus = responseError.convertUserInfo()! - status.errors.count //= 3 - //... - } - -``` - -There's improved type inference where before you had to include the full type signature in the closure continuation: - -```swift -client.getAsync(AppOverview()) - .then(body:{(r:AppOverviewResponse) -> Void in - r.topTechnologies.count //= 100 - ... - }) -``` - -In Swift 2.0 this has now been reduced to the absolute minimum code required: - -```swift -client.getAsync(AppOverview()) - .then { - $0.topTechnologies.count //= 100 - //... - } -``` - -If preferred you can continue marking it up with as much additional Type information or optional syntax as you'd like, e.g: - -```swift -client.getAsync(AppOverview()) - .then({ r in - r.topTechnologies.count //= 100 - //... - }) -``` - -### Download ServiceStack Xcode 7 Plugin - -[![ServiceStackXCode.dmg download](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/servicestackxcode-dmg.png)](https://github.com/ServiceStack/ServiceStack.Swift/raw/master/dist/ServiceStackXcode.dmg) - -Once opened, the ServiceStack XCode Plugin can be installed by dragging it to the XCode Plugins directory: - -![ServiceStackXCode.dmg Installer](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/servicestackxcode-installer.png) - -### Swift 2.0 Changes - -Swift 2.0 is a major upgrade that introduced a number of breaking changes which required updating both Server generated DTO's as -well as `JsonServiceClient` client library. Whilst the POCO DTO definition remained exactly the same, i.e: - -```swift -public class AllCollectionTypes -{ - required public init(){} - public var intArray:[Int] = [] - public var intList:[Int] = [] - public var stringArray:[String] = [] - public var stringList:[String] = [] - public var pocoArray:[Poco] = [] - public var pocoList:[Poco] = [] - public var pocoLookup:[String:[Poco]] = [:] - public var pocoLookupMap:[String:[String:Poco]] = [:] -} -``` - -#### Old Type Extensions - -In Swift 1.x the amount of boilerplate required for transparent JSON serialization without being able to use Swift's incomplete -reflection support required this amount of boilerplate repeated for every type: - -```swift -extension AllCollectionTypes : JsonSerializable -{ - public class var typeName:String { return "AllCollectionTypes" } - public class func reflect() -> Type { - return TypeConfig.config() ?? TypeConfig.configure(Type( - properties: [ - Type.arrayProperty("intArray", get: { $0.intArray }, set: { $0.intArray = $1 }), - Type.arrayProperty("intList", get: { $0.intList }, set: { $0.intList = $1 }), - Type.arrayProperty("stringArray", get: { $0.stringArray }, set: { $0.stringArray = $1 }), - Type.arrayProperty("stringList", get: { $0.stringList }, set: { $0.stringList = $1 }), - Type.arrayProperty("pocoArray", get: { $0.pocoArray }, set: { $0.pocoArray = $1 }), - Type.arrayProperty("pocoList", get: { $0.pocoList }, set: { $0.pocoList = $1 }), - Type.objectProperty("pocoLookup", get: { $0.pocoLookup }, set: { $0.pocoLookup = $1 }), - Type.objectProperty("pocoLookupMap", get: { $0.pocoLookupMap }, set: { $0.pocoLookupMap = $1 }), - ])) - } - public func toJson() -> String { - return AllCollectionTypes.reflect().toJson(self) - } - public class func fromJson(json:String) -> AllCollectionTypes? { - return AllCollectionTypes.reflect().fromJson(AllCollectionTypes(), json: json) - } - public class func fromObject(any:AnyObject) -> AllCollectionTypes? { - return AllCollectionTypes.reflect().fromObject(AllCollectionTypes(), any:any) - } - public func toString() -> String { - return AllCollectionTypes.reflect().toString(self) - } - public class func fromString(string:String) -> AllCollectionTypes? { - return AllCollectionTypes.reflect().fromString(AllCollectionTypes(), string: string) - } -} -``` - -#### New Type Extensions - -This has now been greatly reduced in Swift 2.0 thanks to Protocol Extensions (aka traits) where it's down to just: - -```swift -extension AllCollectionTypes : JsonSerializable -{ - public static var typeName:String { return "AllCollectionTypes" } - public static var metadata = Metadata.create([ - Type.arrayProperty("intArray", get: { $0.intArray }, set: { $0.intArray = $1 }), - Type.arrayProperty("intList", get: { $0.intList }, set: { $0.intList = $1 }), - Type.arrayProperty("stringArray", get: { $0.stringArray }, set: { $0.stringArray = $1 }), - Type.arrayProperty("stringList", get: { $0.stringList }, set: { $0.stringList = $1 }), - Type.arrayProperty("pocoArray", get: { $0.pocoArray }, set: { $0.pocoArray = $1 }), - Type.arrayProperty("pocoList", get: { $0.pocoList }, set: { $0.pocoList = $1 }), - Type.objectProperty("pocoLookup", get: { $0.pocoLookup }, set: { $0.pocoLookup = $1 }), - Type.objectProperty("pocoLookupMap", get: { $0.pocoLookupMap }, set: { $0.pocoLookupMap = $1 }), - ]) -} -``` - -This still doesn't make use any reflection so JSON serialization should continue to perform exceptionally well. - -### New Service Client Features - -During the upgrade we've also added a number of new features to the `JsonServiceClient` where it's public `ServiceClient` -protocol has been expanded to: - -```swift -public protocol ServiceClient -{ - func get(request:T) throws -> T.Return - func get(request:T) throws -> Void - func get(request:T, query:[String:String]) throws -> T.Return - func get(relativeUrl:String) throws -> T - func getAsync(request:T) -> Promise - func getAsync(request:T) -> Promise - func getAsync(request:T, query:[String:String]) -> Promise - func getAsync(relativeUrl:String) -> Promise - - func post(request:T) throws -> T.Return - func post(request:T) throws -> Void - func post(relativeUrl:String, request:Request?) throws -> Response - func postAsync(request:T) -> Promise - func postAsync(request:T) -> Promise - func postAsync(relativeUrl:String, request:Request?) -> Promise - - func put(request:T) throws -> T.Return - func put(request:T) throws -> Void - func put(relativeUrl:String, request:Request?) throws -> Response - func putAsync(request:T) -> Promise - func putAsync(request:T) -> Promise - func putAsync(relativeUrl:String, request:Request?) -> Promise - - func delete(request:T) throws -> T.Return - func delete(request:T) throws -> Void - func delete(request:T, query:[String:String]) throws -> T.Return - func delete(relativeUrl:String) throws -> T - func deleteAsync(request:T) -> Promise - func deleteAsync(request:T) -> Promise - func deleteAsync(request:T, query:[String:String]) -> Promise - func deleteAsync(relativeUrl:String) -> Promise - - func patch(request:T) throws -> T.Return - func patch(request:T) throws -> Void - func patch(relativeUrl:String, request:Request?) throws -> Response - func patchAsync(request:T) -> Promise - func patchAsync(request:T) -> Promise - func patchAsync(relativeUrl:String, request:Request?) -> Promise - - func send(request:T) throws -> T.Return - func send(request:T) throws -> Void - func send(intoResponse:T, request:NSMutableURLRequest) throws -> T - func sendAsync(intoResponse:T, request:NSMutableURLRequest) -> Promise - - func getData(url:String) throws -> NSData - func getDataAsync(url:String) -> Promise -} -``` - -Where new support has been added for `IReturnVoid` and **PATCH** Requests. - -### Swift HTTP Marker Interfaces - -The new `send*` API's take advantage of the HTTP Verb Interface Markers described below to send the Request DTO using the -annotated HTTP Method, e.g: - -```swift -public class HelloByGet : IReturn, IGet -{ - public typealias Return = HelloResponse - public var name:String? -} -public class HelloByPut : IReturn, IPut -{ - public typealias Return = HelloResponse - public var name:String? -} - -let response = try client.send(HelloByGet()) //GET - -client.sendAsync(HelloByPut()) //PUT - .then { } -``` - -ServiceStack's Error Response Status DTO's are now included in the **JsonServiceClient.swift** source instead of being repeated -within each ServiceStack Reference added to your project, mitigating any duplicate DTO conflicts. - -## [Java ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/android-studio-splash.png)](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) - -The Java Android Studio and Eclipse Plugins have also been improved in this release, the new versions which can be downloaded below: - -### [Download ServiceStack IDEA Android Studio Plugin](https://plugins.jetbrains.com/plugin/7749?pr=androidstudio) - -### [Download ServiceStack Eclipse Plugin](https://github.com/ServiceStack/ServiceStack.Java/tree/master/src/ServiceStackEclipse#eclipse-integration-with-servicestack) - -### Send Raw String or byte[] Requests - -You can easily get the raw string Response from Request DTO's that return are annotated with `IReturn`, e.g: - -```java -public static class HelloString implements IReturn { ... } - -String response = client.get(new HelloString().setName("World")); -``` - -You can also specify that you want the raw UTF-8 `byte[]` or `String` response instead of a the deserialized Response DTO by specifying -the Response class you want returned, e.g: - -```java -byte[] response = client.get("/hello?Name=World", byte[].class); -``` - -### Java HTTP Marker Interfaces - -Like the .NET and Swift Service Clients, the HTTP Interface markers are also annotated on Java DTO's and let you use the same -`send` API to send Requests via different HTTP Verbs, e.g: - -```java -public static class HelloByGet implements IReturn, IGet { ... } -public static class HelloByPut implements IReturn, IPut { ... } - -HelloResponse response = client.send(new HelloByGet().setName("World")); //GET - -client.sendAsync(new HelloByPut().setName("World"), //PUT - new AsyncResult() { - @Override - public void success(HelloResponse response) { } - }); -``` - -### IReturnVoid Support - -New Sync/Async overloads have been added for `IReturnVoid` Request DTO's: - -```java -client.delete(new DeleteCustomer().setId(1)); -``` - -### Java Annotations - -The built-in Java Annotations now have their metadata available at runtime as they're now annotated with: - -```java -@Retention(RetentionPolicy.RUNTIME) -public @interface Api { ... } -``` - - -## [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) - -### Export Types - -By default ServiceStack's Native Type Feature doesn't emit any System types built into the .NET Framework, these can now be -emitted for non-.NET Languages with the new `ExportTypes` list, e.g. if your DTO's exposes the `DayOfWeek` System Enum it can -be exported by adding it to the pre-registered NativeTypesFeature's Plugin with: - -```csharp - var nativeTypes = this.GetPlugin(); -nativeTypes.MetadataTypesConfig.ExportTypes.Add(typeof(DayOfWeek)); -``` - -Now if any of your DTO's has a `DayOfWeek` property it will emitted in the generated DTO's, Java example: - -```java -public static enum DayOfWeek -{ - Sunday, - Monday, - Tuesday, - Wednesday, - Thursday, - Friday, - Saturday; -} -``` - -## Service Clients - -### HTTP Verb Interface Markers - -You can decorate your Request DTO's using the `IGet`, `IPost`, `IPut`, `IDelete` and `IPatch` interface markers and the `Send` and -`SendAsync` API's will use it to automatically send the Request using the selected HTTP Method. E.g: - -```csharp -public class HelloByGet : IReturn, IGet -{ - public string Name { get; set; } -} -public class HelloByPut : IReturn, IPut -{ - public string Name { get; set; } -} - -var response = client.Send(new HelloByGet { Name = "World" }); //GET - -await client.SendAsync(new HelloByPut { Name = "World" }); //PUT -``` - -This was feature was previously only implemented in -[StripeGateway](https://github.com/ServiceStack/Stripe), but is now available in all -[.NET Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) as well as the latest -[Java JsonServiceClient](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) and -[Swift JsonServiceClient](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference). - -Whilst a simple feature, it enables treating your remote services as a message-based API -[yielding its many inherent advantages](https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services#advantages-of-message-based-designs) -where your Application API's need only pass Request DTO models around to be able to invoke remote Services, decoupling the -Service Request from its implementation which can be now easily managed by a high-level adapter that takes care of proxying the -Request to the underlying Service Client. The adapter could also add high-level functionality of it's own including auto retrying of -failed requests, generic error handling, logging/telemetrics, event notification, throttling, offline queuing/syncing, etc. - -## [Async StripeGatway](https://github.com/ServiceStack/Stripe) - -Perhaps a clearer indication of the simplicity and generic functionality possible from a message-based API's is how it's possible -to add [Async support to **all** Stripe Gateway API's](https://github.com/ServiceStack/Stripe/issues/20) in **<1 hour** from initial -feature request to [implementation](https://github.com/ServiceStack/Stripe/commit/aa4023ef4d0cbe74187b72af567038f688fd9920) -and published to our -[MyGet pre-release NuGet packages](https://github.com/ServiceStack/ServiceStack/wiki/MyGet) where it's available for immediate use: - -```csharp -var charge = await gateway.PostAsync(new ChargeStripeCustomer { - Customer = customer.Id, - Amount = 100, - Currency = "usd", - Description = "Test Charge Customer", -}); -``` - -The Stripe Gateway provides a typed .NET message-based API to -[Stripe's REST Services](https://stripe.com/docs/api#intro) which as it's inspired by Ruby conventions, uses a `snake_case` naming -convention so it's a good example of viewing the benefits of a message-based API's in isolation, i.e. independent from the features -ServiceStack adds around it's own .NET Services. - -Unlike other Stripe Client implementations the [StripeGateway.cs](https://github.com/ServiceStack/Stripe/blob/master/src/Stripe/StripeGateway.cs) is - - - **Small** - Fits in a single class where the majority of the code-base contains Stripe's Typed DTO's and Currency Info - - **Simple** - Its tiny code-base has great re-use, requiring less effort to create, maintain, extend and test - - **Highly Testable** - Its small surface area implements the typed, mockable - [IRestGateway](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/IRestGateway.cs) - - **Open Ended** - Users can use their own Request DTO's to call new Stripe Services that StripeGateway has no knowledge about - -### Declarative Message-based APIs - -The only custom code required to implement the `ChargeStripeCustomer` above is this single, clean, declarative Request DTO: - -```csharp -[Route("/charges")] -public class ChargeStripeCustomer : IPost, IReturn -{ - public int Amount { get; set; } - public string Currency { get; set; } - public string Customer { get; set; } - public string Card { get; set; } - public string Description { get; set; } - public bool? Capture { get; set; } - public int? ApplicationFee { get; set; } -} -``` - -Which contains all the information needed to call the Stripe Service including the `/charges` relative url, using the **POST** -HTTP method and the typed `StripeCharge` DTO it returns. To charge a Customer the Request DTO can either use the explicit -`Post/PostAsync` or universal `Send/SendAsync` StripeGateway methods. - -We hope this example makes it clearer why we continue to encourage others to adopt a message-based API for accessing any remote -Services and how we're able to continue to deliver rich generic functionality and value to all ServiceStack Services with -minimal code, effort, friction and complexity as a result. - -## Debuggable Razor Views - -Razor Views are now debuggable for -[Debug builds](https://github.com/ServiceStack/ServiceStack/wiki/Debugging#debugmode) by default, it can also be explicitly specified on: - -```csharp -Plugins.Add(new RazorFormat { - IncludeDebugInformation = true, - CompileFilter = compileParams => ... -}) -``` - -> The new `CompileFilter` is an advanced option that lets modify the `CompilerParameters` used by the C# CodeDom provider to compile -the Razor Views if needed. - - -## [ss-utils.js](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library) - -### $.fn.ajaxSubmit - -ajaxSubmit has been decoupled from ServiceStack's -[auto bindForm ajax and validation helper](https://github.com/ServiceStack/ServiceStack/wiki/ss-utils.js-JavaScript-Client-Library#binding-html-forms) -so it can be used independently to submit a form on demand. This is used in the -[connections.jsx](https://github.com/ServiceStackApps/RedisReact/blob/15dfc5cfea49d0502ec8c090b5b180d29051ea3a/src/RedisReact/RedisReact/js/components/connections.jsx#L31) -React Component of [Redis React's Connections Page](https://github.com/ServiceStackApps/RedisReact#connections) -to auto submit the form via ajax to the specified `/connection` url with the populated Form INPUT values. It also disables the -`#btnConnect` submit button and adds a `.loading` class to the form whilst it's in transit which is used to temporarily show the -loading sprite: - -```js -var Connections = React.createClass({ - //... - onSubmit: function (e) { - e.preventDefault(); - - var $this = this; - $(e.target).ajaxSubmit({ - onSubmitDisable: $("#btnConnect"), - success: function () { - $this.setState({ successMessage: "Connection was changed" }); - Actions.loadConnection(); - } - }); - }, - render: function () { - var conn = this.state.connection; - return ( -
      -
      -
      -

      Redis Connection

      -
      - - - -
      -

      - - -

      -

      {this.state.successMessage}

      -

      - -
      -
      - ); - } -}; -``` - -### $.ss.parseResponseStatus - -Lets you easily parse the raw text of a Ajax Error Response into a responseStatus JavaScript object, example used in Redis React's -[Console Component](https://github.com/ServiceStackApps/RedisReact/blob/15dfc5cfea49d0502ec8c090b5b180d29051ea3a/src/RedisReact/RedisReact/js/components/console.jsx#L103): - -```js -.fail(function (jq, jqStatus, statusDesc) { - var status = $.ss.parseResponseStatus(jq.responseText, statusDesc); - Actions.logEntry({ - cmd: cmd, - result: status.message, - stackTrace: status.stackTrace, - type: 'err', - }); -}); -``` - -### $.ss.bindAll - -The new `bindAll` API is a simple helper for creating lightweight JavaScript objects by binding `this` for all functions of an -object literal to the object instance, e.g: - -```js -var Greeting = $.ss.bindAll({ - name: "World", - sayHello: function() { - alert("Hello, " + this.name); - } -}); - -var fn = Greeting.sayHello; -fn(); // Hello, World -``` - -## Redis - -### Improved LUA support - -The new `ExecLua` API lets you execute LUA Script on a Redis server and returns any result in a generic `RedisText` Type which can -be easily be inspected to access the LUA Script's complex type response. A good example of when to use a server-side LUA script -is to reduce the network latency of chatty multi-request API's. - -A prime example of this is when using Redis's [SCAN](http://redis.io/commands/scan) API which provides a streaming, non-blocking -API to search through the entire Redis KeySet. The number of API calls that's required is bounded to the size of the Redis -KeySet which could quickly result in a large number of Redis Operations yielding an unacceptable delay due to the latency of -multiple dependent remote network calls. - -An easy solution is to instead have the multiple SCAN calls performed in-process on the Redis Server, eliminating the -network latency of multiple SCAN calls, e.g: - -```csharp -const string FastScanScript = @" -local limit = tonumber(ARGV[2]) -local pattern = ARGV[1] -local cursor = 0 -local len = 0 -local results = {} -repeat - local r = redis.call('scan', cursor, 'MATCH', pattern, 'COUNT', limit) - cursor = tonumber(r[1]) - for k,v in ipairs(r[2]) do - table.insert(results, v) - len = len + 1 - if len == limit then break end - end -until cursor == 0 or len == limit -return results"; - -RedisText r = redis.ExecLua(FastScanScript, "key:*", "10"); -r.Children.Count.Print() //= 10 -``` - -The `ExecLua` API returns this complex LUA table response in the `Children` collection of the `RedisText` Response. - -This above API is equivalent to C# API below which returns the first 10 results matching the `key:*` pattern: - -```csharp -var keys = Redis.ScanAllKeys(pattern: "key:*", pageSize: 10) - .Take(10).ToList(); -``` - -However the C# Streaming API above would require an unknown number of Redis Operations to complete the request whereas -only 1 call to Redis is required for the LUA Script. The number of SCAN calls can be reduced by choosing a higher pageSize -to tell Redis to scan more keys. - -### ExecCachedLua - -ExecCachedLua is a convenient high-level API that eliminates the bookkeeping required for executing high-performance server LUA -Scripts which suffers from many of the problems that RDBMS stored procedures have which depends on pre-existing state in the RDBMS -that needs to be updated with the latest version of the Stored Procedure. - -With Redis LUA you either have the option to send, parse, load then execute the entire LUA script each time it's called or -alternatively you could pre-load the LUA Script into Redis once on StartUp and then execute it using the Script's SHA1 hash. -The issue with this is that if the Redis server is accidentally flushed you're left with a broken application relying on a -pre-existing script that's no longer there. The new `ExecCachedLua` API provides the best of both worlds where it will always -execute the compiled SHA1 script, saving bandwidth and CPU but will also re-create the LUA Script if it no longer exists. - -You can now execute the compiled LUA script above by its SHA1 identifier, which continues to work regardless if it never existed -or was removed at runtime, e.g: - -```csharp -// #1: Loads LUA script and caches SHA1 hash in Redis Client -r = redis.ExecCachedLua(FastScanScript, sha1 => - redis.ExecLuaSha(sha1, "key:*", "10")); - -// #2: Executes using cached SHA1 hash -r = redis.ExecCachedLua(FastScanScript, sha1 => - redis.ExecLuaSha(sha1, "key:*", "10")); - -// Deletes all existing compiled LUA scripts -redis.ScriptFlush(); - -// #3: Executes using cached SHA1 hash, gets NOSCRIPT Error, re-creates and re-executes with SHA1 hash -r = redis.ExecCachedLua(FastScanScript, sha1 => - redis.ExecLuaSha(sha1, "key:*", "10")); -``` - -### New Redis Client APIs - -All new APIs added in this release: - -#### IRedisClient - - Type - returns key Type as string that can be used in pipelines - - GetStringCount - returns STRLEN in a consistent API to fetch size of value, i.e `Get{DataType}Count()` - - SetValues - Set multiple String values, alias for SetAll - - ExecLua - Execute Lua Script that returns a generic `RedisText` result - - ExecLuaSha - Execute Lua Script by SHA1 which returns a generic `RedisText` result - - ExecCachedLua - Execute Lua Script by SHA1, re-creating it if it no longer exists - -#### IRedisNativeClient - - Type - returns key Type as string that can be used in pipelines - - EvalCommand - Execute Lua Script that returns a generic `RedisData` byte[] result - - EvalShaCommand - Execute Lua Script by SHA1 which returns a generic `RedisData` byte[] result - -## [Caching](https://github.com/ServiceStack/ServiceStack/wiki/Caching) - -The [ICacheClientExtended](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Caching/ICacheClientExtended.cs) -API is used to to provide additional non-core functionality to our most popular -[Caching providers](https://github.com/ServiceStack/ServiceStack/wiki/Caching): - - - Redis - - OrmLite RDBMS - - In Memory - - AWS - -The new API's are added as Extension methods on `ICacheClient` so they're easily accessible without casting, the new API's available include: - - - GetKeysByPattern(pattern) - return keys matching a wildcard pattern - - GetAllKeys() - return all keys in the caching provider - - GetKeysStartingWith() - Streaming API to return all keys Starting with a prefix - -With these new API's you can now easily get all active User Sessions using any of the supported Caching providers above with: - -```csharp -var sessionPattern = IdUtils.CreateUrn(""); //= urn:iauthsession: -var sessionKeys = Cache.GetKeysStartingWith(sessionPattern).ToList(); - -var allSessions = Cache.GetAll(sessionKeys); -``` - -### Minor Features - - - All 3rd Party NuGet dependencies updated to latest stable version - - C# `FormatException` return 400 by default - - New `AuthServerFilter` and `AuthClientFilter` available to all DotNetOpenAuth OAuth2 Providers - - [Patch added on JavaScript JsonServiceClient](https://github.com/ServiceStack/ServiceStack/commit/5c9199ff6f66b86208efc20215d22c7b304048de) -by [@DeonHeyns](https://github.com/DeonHeyns) - - Added `UnsafeOrderBy()` to OrmLite SqlExpression to allow unchecked ordering by results by Custom SQL - - -# v4.0.44 Release Notes - -## Highly Available Redis - -[Redis Sentinel](http://redis.io/topics/sentinel) is the official recommendation for running a highly -available Redis configuration by running a number of additional redis sentinel processes to actively monitor -existing redis master and slave instances ensuring they're each working as expected. If by consensus it's -determined that the master is no longer available it will automatically failover and promote one of the -replicated slaves as the new master. The sentinels also maintain an authoritative list of available -redis instances providing clients a centeral repositorty to discover available instances they can connect to. - -Support for Redis Sentinel has been added with the `RedisSentinel` class which listens to the available -Sentinels to source its list of available master, slave and other sentinel redis instances which it uses -to configure and maintain the Redis Client Managers, initiating any failovers as they're reported. - -### RedisSentinel Usage - -To use the new Sentinel support, instead of populating the Redis Client Managers with the connection string -of the master and slave instances you would create a single `RedisSentinel` instance configured with -the connection string of the running Redis Sentinels: - -```csharp -var sentinelHosts = new[]{ "sentinel1", "sentinel2:6390", "sentinel3" }; -var sentinel = new RedisSentinel(sentinelHosts, masterName: "mymaster"); -``` - -This shows a typical example of configuring a `RedisSentinel` which references 3 sentinel hosts (i.e. -the minimum number for a highly available setup which can survive any node failing). -It's also configured to look at the `mymaster` configuration set (the default master group). - -> Redis Sentinels can monitor more than 1 master / slave group, each with a different master group name. - -The default port for sentinels is **26379** (when unspecified) and as RedisSentinel can auto-discover -other sentinels, the minimum configuration required is just: - -```csharp -var sentinel = new RedisSentinel("sentinel1"); -``` - -> Scanning and auto discovering of other Sentinels can be disabled with `ScanForOtherSentinels=false` - -### Start monitoring Sentinels - -Once configured, you can start monitoring the Redis Sentinel servers and access the pre-configured -client manager with: - -```csharp -IRedisClientsManager redisManager = sentinel.Start(); -``` - -Which as before, can be registered in your preferred IOC as a **singleton** instance: - -```csharp -container.Register(c => sentinel.Start()); -``` - -### Advanced Sentinel Configuration - -RedisSentinel by default manages a configured `PooledRedisClientManager` instance which resolves both master -Redis clients for read/write `GetClient()` and slaves for readonly `GetReadOnlyClient()` API's. - -This can be changed to use the newer `RedisManagerPool` with: - -```csharp -sentinel.RedisManagerFactory = (master,slaves) => new RedisManagerPool(master); -``` - -### Custom Redis Connection String - -The host the RedisSentinel is configured with only applies to that Sentinel Host, you can still use the flexibility of -[Redis Connection Strings](https://github.com/ServiceStack/ServiceStack.Redis#redis-connection-strings) -to configure the individual Redis Clients by specifying a custom `HostFilter`: - -```csharp -sentinel.HostFilter = host => "{0}?db=1&RetryTimeout=5000".Fmt(host); -``` - -This will return clients configured to use Database 1 and a Retry Timeout of 5 seconds (used in new -Auto Retry feature). - -### Other RedisSentinel Configuration - -Whilst the above covers the popular Sentinel configuration that would typically be used, nearly every aspect -of `RedisSentinel` behavior is customizable with the configuration below: - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      OnSentinelMessageReceivedFired when the Sentinel worker receives a message from the Sentinel Subscription
      OnFailoverFired when Sentinel fails over the Redis Client Manager to a new master
      OnWorkerErrorFired when the Redis Sentinel Worker connection fails
      IpAddressMapMap internal redis host IP's returned by Sentinels to its external IP
      ScanForOtherSentinelsWhether to routinely scan for other sentinel hosts (default true)
      RefreshSentinelHostsAfterWhat interval to scan for other sentinel hosts (default 10 mins)
      WaitBetweenFailedHostsHow long to wait after failing before connecting to next redis instance (default 250ms)
      MaxWaitBetweenFailedHostsHow long to retry connecting to hosts before throwing (default 60s)
      WaitBeforeForcingMasterFailoverHow long after consecutive failed attempts to force failover (default 60s)
      ResetWhenSubjectivelyDownReset clients when Sentinel reports redis is subjectively down (default true)
      ResetWhenObjectivelyDownReset clients when Sentinel reports redis is objectively down (default true)
      SentinelWorkerConnectTimeoutMsThe Max Connection time for Sentinel Worker (default 100ms)
      SentinelWorkerSendTimeoutMsMax TCP Socket Send time for Sentinel Worker (default 100ms)
      SentinelWorkerReceiveTimeoutMsMax TCP Socket Receive time for Sentinel Worker (default 100ms)
      - -## [Configure Redis Sentinel Servers](https://github.com/ServiceStack/redis-config) - -[![Instant Redis Setup](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/redis/instant-sentinel-setup.png)](https://github.com/ServiceStack/redis-config) - -We've also created the -[redis config project](https://github.com/ServiceStack/redis-config) -to simplify setting up and running a highly-available multi-node Redis Sentinel configuration including -start/stop scripts for instantly setting up the minimal -[highly available Redis Sentinel configuration](https://github.com/ServiceStack/redis-config/blob/master/README.md#3x-sentinels-monitoring-1x-master-and-2x-slaves) -on a single (or multiple) Windows, OSX or Linux servers. This single-server/multi-process configuration -is ideal for setting up a working sentinel configuration on a single dev workstation or remote server. - -The redis-config repository also includes the -[MS OpenTech Windows redis binaries](https://github.com/ServiceStack/redis-windows#running-microsofts-native-port-of-redis) -and doesn't require any software installation. - -### Windows Usage - -To run the included Sentinel configuration, clone the redis-config repo on the server you want to run it on: - - git clone https://github.com/ServiceStack/redis-config.git - -Then Start 1x Master, 2x Slaves and 3x Sentinel redis-servers with: - - cd redis-config\sentinel3\windows - start-all.cmd - -Shutdown started instances: - - stop-all.cmd - -If you're running the redis processes locally on your dev workstation the minimal configuration to connect -to the running instances is just: - -```csharp -var sentinel = new RedisSentinel("127.0.0.1:26380"); -container.Register(c => sentinel.Start()); -``` - -### Localhost vs Network IP's - -The sentinel configuration assumes all redis instances are running locally on **127.0.0.1**. -If you're instead running it on a remote server that you want all developers in your network to be -able to access, you'll need to either change the IP Address in the `*.conf` files to use the servers -Network IP. Otherwise you can leave the defaults and use the `RedisSentinel` IP Address Map feature -to transparently map localhost IP's to the Network IP that each pc on your network can connect to. - -E.g. if this is running on a remote server with a **10.0.0.9** Network IP, it can be configured with: - -```csharp -var sentinel = new RedisSentinel("10.0.0.9:26380") { - IpAddressMap = { - {"127.0.0.1", "10.0.0.9"}, - } -}; -container.Register(c => sentinel.Start()); -``` - -### Google Cloud - [Click to Deploy Redis](https://github.com/ServiceStack/redis-config/blob/master/README.md#google-cloud---click-to-deploy-redis) - -The easiest Cloud Service we've found that can instantly set up a multi node-Redis Sentinel Configuration -is using Google Cloud's -[click to deploy Redis feature](https://cloud.google.com/solutions/redis/click-to-deploy) -available from the Google Cloud Console under **Deploy & Manage**: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/redis/sentinel3-gcloud-01.png) - -Clicking **Deploy** button will let you configure the type, size and location where you want to deploy the -Redis VM's. See the -[full Click to Deploy Redis guide](https://github.com/ServiceStack/redis-config/blob/master/README.md#google-cloud---click-to-deploy-redis) -for a walk-through on setting up and inspecting a highly-available redis configuration on Google Cloud. - -## Automatic Retries - -Another feature we've added to improve reliability is Auto Retry where the RedisClient will transparently -retry failed Redis operations due to Socket and I/O Exceptions in an exponential backoff starting from -**10ms** up until the `RetryTimeout` of **3000ms**. These defaults can be tweaked with: - -```csharp -RedisConfig.DefaultRetryTimeout = 3000; -RedisConfig.BackOffMultiplier = 10; -``` - -The `RetryTimeout` can also be configured on the connection string with `?RetryTimeout=3000`. - -## RedisConfig - -The `RedisConfig` static class has been expanded to provide an alternative to Redis Connection Strings to -configure the default RedisClient settings. Each config option is -[documented on the RedisConfig class](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/src/ServiceStack.Redis/RedisConfig.cs) -with the defaults shown below: - -```csharp -class RedisConfig -{ - DefaultConnectTimeout = -1 - DefaultSendTimeout = -1 - DefaultReceiveTimeout = -1 - DefaultRetryTimeout = 3 * 1000 - DefaultIdleTimeOutSecs = 240 - BackOffMultiplier = 10 - BufferLength = 1450 - BufferPoolMaxSize = 500000 - VerifyMasterConnections = true - HostLookupTimeoutMs = 200 - AssumeServerVersion = null - DeactivatedClientsExpiry = TimeSpan.FromMinutes(1) - DisableVerboseLogging = false -} -``` - -One option you may want to set is `AssumeServerVersion` with the version of Redis Server version you're running, e.g: - -```csharp -RedisConfig.AssumeServerVersion = 2812; //2.8.12 -RedisConfig.AssumeServerVersion = 3030; //3.0.3 -``` - -This is used to change the behavior of a few API's to use the most optimal Redis Operation for their server -version. Setting this will **save an additional INFO lookup** each time a new RedisClient Connection is opened. - -## RedisStats - -The new -[RedisStats](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/src/ServiceStack.Redis/RedisStats.cs) -class provides better visibility and introspection into your running instances: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      TotalCommandsSent Total number of commands sent
      TotalFailovers Number of times the Redis Client Managers have FailoverTo() either by sentinel or manually
      TotalDeactivatedClients Number of times a Client was deactivated from the pool, either by FailoverTo() or exceptions on client
      TotalFailedSentinelWorkers Number of times connecting to a Sentinel has failed
      TotalForcedMasterFailovers Number of times we've forced Sentinel to failover to another master due to consecutive errors
      TotalInvalidMasters Number of times a connecting to a reported Master wasn't actually a Master
      TotalNoMastersFound Number of times no Masters could be found in any of the configured hosts
      TotalClientsCreated Number of Redis Client instances created with RedisConfig.ClientFactory
      TotalClientsCreatedOutsidePool Number of times a Redis Client was created outside of pool, either due to overflow or reserved slot was overridden
      TotalSubjectiveServersDown Number of times Redis Sentinel reported a Subjective Down (sdown)
      TotalObjectiveServersDown Number of times Redis Sentinel reported an Objective Down (odown)
      TotalRetryCount Number of times a Redis Request was retried due to Socket or Retryable exception
      TotalRetrySuccess Number of times a Request succeeded after it was retried
      TotalRetryTimedout Number of times a Retry Request failed after exceeding RetryTimeout
      TotalPendingDeactivatedClients Total number of deactivated clients that are pending being disposed
      - -You can get and print a dump of all the stats at anytime with: - -```csharp -RedisStats.ToDictionary().PrintDump(); -``` - -And Reset all Stats back to `0` with `RedisStats.Reset()`. - -### Injectable Resolver Strategy - -To support the different host resolution behavior required for Redis Sentinel, we've decoupled the Redis -Host Resolution behavior into an injectable strategy which can be overridden by implementing -[IRedisResolver](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/src/ServiceStack.Redis/IRedisResolver.cs) -and injected into any of the Redis Client Managers with: - -```csharp -redisManager.RedisResolver = new CustomHostResolver(); -``` - -Whilst this an advanced customization option not expected to be used, it does allow using a custom strategy to -change which Redis hosts to connect to. See the -[RedisResolverTests](https://github.com/ServiceStack/ServiceStack.Redis/blob/master/tests/ServiceStack.Redis.Tests.Sentinel/RedisResolverTests.cs) -for more info. - -### New APIs - - - PopItemsFromSet() - - DebugSleep() - - GetServerRole() - -The `RedisPubSubServer` is now able to listen to a **pattern** of multiple channels with: - -```csharp -var redisPubSub = new RedisPubSubServer(redisManager) { - ChannelsMatching = new[] { "events.in.*", "events.out." } -}; -redisPubSub.Start(); -``` - -### Deprecated APIs - - - The `SetEntry*` API's have been deprecated in favor of the more appropriately named `SetValue*` API's - -## OrmLite Converters! - -OrmLite has become a lot more customizable and extensible thanks to the internal redesign decoupling all -custom logic for handling different Field Types into individual Type Converters. -This redesign makes it possible to enhance or entirely replace how .NET Types are handled. OrmLite can now -be extended to support new Types it has no knowledge about, a feature taken advantage of by the new support -for SQL Server's `SqlGeography`, `SqlGeometry` and `SqlHierarchyId` Types! - -Despite the scope of this internal refactor, OrmLite's existing test suite (and a number of new tests) continue -to pass for each supported RDBMS. Whilst the **Firebird** and **VistaDB** providers having been greatly improved -and now also pass the existing test suite (RowVersion's the only feature not implemented in VistaDB due -to its lack of triggers). - -![OrmLite Converters](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/ormlite-converters.png) - -### Improved encapsulation, reuse, customization and debugging - -Converters allows for greater re-use where the common functionality to support each type is maintained in the common -[ServiceStack.OrmLite/Converters](https://github.com/ServiceStack/ServiceStack.OrmLite/tree/master/src/ServiceStack.OrmLite/Converters) -whilst any RDBMS-specific functionality can inherit the common converters and provide any specialization -required to support that type. E.g. SQL Server specific converters are maintained in -[ServiceStack.OrmLite.SqlServer/Converters](https://github.com/ServiceStack/ServiceStack.OrmLite/tree/master/src/ServiceStack.OrmLite.SqlServer/Converters) -with each converter inheriting shared functionality and only adding custom logic required to support that -Type in Sql Server. - -### Creating Converters - -They also provide better encapsulation since everything relating to handling the field type is contained within -a single class definition. A Converter is any class implementing -[IOrmLiteConverter](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite/IOrmLiteConverter.cs) -although it's instead recommended to inherit from the `OrmLiteConverter` abstract class which allows -only the minimum API's needing to be overridden, namely the `ColumnDefinition` -used when creating the Table definition and the ADO.NET `DbType` it should use in parameterized queries. -An example of this is in -[GuidConverter](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite/Converters/GuidConverter.cs): - -```csharp -public class GuidConverter : OrmLiteConverter -{ - public override string ColumnDefinition - { - get { return "GUID"; } - } - - public override DbType DbType - { - get { return DbType.Guid; } - } -} -``` - -But for this to work in SQL Server the `ColumnDefinition` should instead be **UniqueIdentifier** which is also -what it needs to be cast to, to be able to query Guid's in an SQL Statement. -Therefore it requires a custom -[SqlServerGuidConverter](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite.SqlServer/Converters/SqlServerGuidConverter.cs) -to support Guids in SQL Server: - -```csharp -public class SqlServerGuidConverter : GuidConverter -{ - public override string ColumnDefinition - { - get { return "UniqueIdentifier"; } - } - - public override string ToQuotedString(Type fieldType, object value) - { - var guidValue = (Guid)value; - return string.Format("CAST('{0}' AS UNIQUEIDENTIFIER)", guidValue); - } -} -``` - -### Registering Converters - -To get OrmLite to use this new Custom Converter for SQL Server, the `SqlServerOrmLiteDialectProvider` just -[registers it in its constructor](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/41226795fc12f1b65d6af70c177a5ff57fa70334/src/ServiceStack.OrmLite.SqlServer/SqlServerOrmLiteDialectProvider.cs#L41): - -```csharp -base.RegisterConverter(new SqlServerGuidConverter()); -``` - -Overriding the pre-registered `GuidConverter` to enable its extended functionality in SQL Server. - -You'll also use the `RegisterConverter()` API to register your own Custom GuidCoverter on the RDBMS -provider you want it to apply to, e.g for SQL Server: - -```csharp -SqlServerDialect.Provider.RegisterConverter(new MyCustomGuidConverter()); -``` - -### Resolving Converters - -If needed, it can be later retrieved with: - -```csharp -IOrmLiteConverter converter = SqlServerDialect.Provider.GetConverter(); -var myGuidConverter = (MyCustomGuidConverter)converter; -``` - -### Debugging Converters - -Custom Converters can also enable a better debugging story where if you want to see what value gets retrieved -from the database, you can override and add a breakpoint on the base method letting you inspect the value -returned from the ADO.NET Data Reader: - -```csharp -public class MyCustomGuidConverter : SqlServerGuidConverter -{ - public overridde object FromDbValue(Type fieldType, object value) - { - return base.FromDbValue(fieldType, value); //add breakpoint - } -} -``` - -### Enhancing an existing Converter - -An example of when you'd want to do this is if you wanted to use the `Guid` property in your POCO's on -legacy tables which stored Guids in `VARCHAR` columns, in which case you can also add support for converting -the returned strings back into Guid's with: - -```csharp -public class MyCustomGuidConverter : SqlServerGuidConverter -{ - public overridde object FromDbValue(Type fieldType, object value) - { - var strValue = value as string; - return strValue != null - ? new Guid(strValue); - : base.FromDbValue(fieldType, value); - } -} -``` - -### Override handling of existing Types - -Another popular Use Case now enabled with Converters is being able to override built-in functionality based -on preference. E.g. By default TimeSpans are stored in the database as Ticks in a `BIGINT` column since it's -the most reliable way to retain the same TimeSpan value uniformly across all RDBMS's. - -E.g SQL Server's **TIME** data type can't store Times greater than 24 hours or with less precision than **3ms**. -But if using a **TIME** column was preferred it can now be enabled by registering to use the new -[SqlServerTimeConverter](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite.SqlServer/Converters/SqlServerTimeConverter.cs) -instead: - -```csharp -SqlServerDialect.Provider.RegisterConverter(new SqlServerTimeConverter { - Precision = 7 -}); -``` - -### Customizable Field Definitions - -Another benefit is they allow for easy customization as seen with `Precision` property which will now -create tables using the `TIME(7)` Column definition for TimeSpan properties. - -For RDBMS's that don't have a native `Guid` type like Oracle or Firebird, you had an option to choose whether -you wanted to save them as text for better readability (default) or in a more efficient compact binary format. -Previously this preference was maintained in a boolean flag along with multiple Guid implementations hard-coded -at different entry points within each DialectProvider. This complexity has now been removed, now to store guids -in a compact binary format you'll instead register the preferred Converter implementation, e.g: - -```csharp -FirebirdDialect.Provider.RegisterConverter( - new FirebirdCompactGuidConverter()); -``` - -### Changing String Column Behavior - -This is another area improved with Converters where previously any available field customizations required -maintaining state inside each provider. Now any customizations are encapsulated within each Converter and -can be modified directly on its concrete Type without unnecessarily polluting the surface area of the primary -[IOrmLiteDialectProvider](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite/IOrmLiteDialectProvider.cs) -which used to create new API's every time a new customization option was added. - -Now to customize the behavior of how strings are stored you can change them directly on the `StringConverter`, e.g: - -```csharp -StringConverter converter = OrmLiteConfig.DialectProvider.GetStringConverter(); -converter.UseUnicode = true; -converter.StringLength = 100; -``` - -Which will change the default column definitions for strings to use `NVARCHAR(100)` for RDBMS's that support -Unicode or `VARCHAR(100)` for those that don't. - -The `GetStringConverter()` API is just an extension method wrapping the generic `GetConverter()` API to return -a concrete type: - -```csharp -public static StringConverter GetStringConverter(this IOrmLiteDialectProvider dialect) -{ - return (StringConverter)dialect.GetConverter(typeof(string)); -} -``` - -Typed extension methods are also provided for other popular types offering additional customizations including -`GetDecimalConverter()` and `GetDateTimeConverter()`. - -### Specify the DateKind in DateTimes - -It's now much simpler and requires less effort to implement new features that maintain the same behavior -across all supported RDBM's thanks to better cohesion, re-use and reduced internal state. One new feature -we've added as a result is the new `DateStyle` customization on `DateTimeConverter` which lets you change how -Date's are persisted and populated, e.g: - -```csharp -DateTimeConverter converter = OrmLiteConfig.DialectProvider.GetDateTimeConverter(); -converter.DateStyle = DateTimeKind.Local; -``` - -Will save `DateTime` in the database and populate them back on data models as LocalTime. -This is also available for Utc: - -```csharp -converter.DateStyle = DateTimeKind.Utc; -``` - -Default is `Unspecified` which doesn't do any conversions and just uses the DateTime returned by the ADO.NET provider. -Examples of the behavior of the different DateStyle's is available in -[DateTimeTests](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/tests/ServiceStack.OrmLite.Tests/DateTimeTests.cs). - -### SQL Server Special Type Converters! - -Just as the ground work for Converters were laid down, [@KevinHoward](https://github.com/KevinHoward) from the -ServiceStack Community noticed OrmLite could now be extended to support new Types and promptly contributed -Converters for SQL Server-specific -[SqlGeography](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite.SqlServer.Converters/SqlServerGeographyTypeConverter.cs), -[SqlGeometry](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite.SqlServer.Converters/SqlServerGeometryTypeConverter.cs) -and -[SqlHierarchyId](https://github.com/ServiceStack/ServiceStack.OrmLite/blob/master/src/ServiceStack.OrmLite.SqlServer.Converters/SqlServerHierarchyIdTypeConverter.cs) -Types! - -Since these Types require an external dependency to the **Microsoft.SqlServer.Types** NuGet package they're -contained in a separate NuGet package that can be installed with: - - PM> Install-Package ServiceStack.OrmLite.SqlServer.Converters - -Alternative Strong-named version: - - PM> Install-Package ServiceStack.OrmLite.SqlServer.Converters.Signed - -Once installed, all available SQL Server Types can be registered on your SQL Server Provider with: - -```csharp -SqlServerConverters.Configure(SqlServer2012Dialect.Provider); -``` - -#### Example Usage - -After the Converters are registered they can treated like a normal .NET Type, e.g: - -**SqlHierarchyId** Example: - -```csharp -public class Node { - [AutoIncrement] - public long Id { get; set; } - public SqlHierarchyId TreeId { get; set; } -} - -db.DropAndCreateTable(); - -var treeId = SqlHierarchyId.Parse("/1/1/3/"); // 0x5ADE is hex -db.Insert(new Node { TreeId = treeId }); - -var parent = db.Scalar(db.From().Select("TreeId.GetAncestor(1)")); -parent.ToString().Print(); //= /1/1/ -``` - -**SqlGeography** and **SqlGeometry** Example: - -```csharp -public class GeoTest { - public long Id { get; set; } - public SqlGeography Location { get; set; } - public SqlGeometry Shape { get; set; } -} - -db.DropAndCreateTable(); - -var geo = SqlGeography.Point(40.6898329,-74.0452177, 4326); // Statue of Liberty - -// A simple line from (0,0) to (4,4) Length = SQRT(2 * 4^2) -var wkt = new System.Data.SqlTypes.SqlChars("LINESTRING(0 0, 4 4)".ToCharArray()); -var shape = SqlGeometry.STLineFromText(wkt, 0); - -db.Insert(new GeoTestTable { Id = 1, Location = geo, Shape = shape }); -var dbShape = db.SingleById(1).Shape; - -new { dbShape.STEndPoint().STX, dbShape.STEndPoint().STY }.PrintDump(); -``` - -Output: - - { - STX: 4, - STY: 4 - } - -### New SQL Server 2012 Dialect Provider - -There's a new `SqlServer2012Dialect.Provider` to take advantage of optimizations available in recent versions -of SQL Server, that's now recommended for use with SQL Server 2012 and later. - -```csharp -container.Register(c => - new OrmLiteConnectionFactory(connString, SqlServer2012Dialect.Provider); -``` - -The new `SqlServer2012Dialect` takes advantage of SQL Server's new **OFFSET** and **FETCH** support to enable more -[optimal paged queries](http://dbadiaries.com/new-t-sql-features-in-sql-server-2012-offset-and-fetch) -that replaces the -[Windowing Function hack](http://stackoverflow.com/a/2135449/85785) -required to support earlier versions of SQL Server. - -### Nested Typed Sub SqlExpressions - -The `Sql.In()` API has been expanded by [Johann Klemmack](https://github.com/jklemmack) to support nesting -and combining of multiple Typed SQL Expressions together in a single SQL Query, e.g: - -```csharp -var usaCustomerIds = db.From(c => c.Country == "USA").Select(c => c.Id); -var usaCustomerOrders = db.Select(db.From() - .Where(q => Sql.In(q.CustomerId, usaCustomerIds))); -``` - -### Descending Indexes - -Descending composite Indexes can be declared with: - - ```csharp -[CompositeIndex("Field1", "Field2 DESC")] -public class Poco { ... } -``` - -### Dapper Updated - -The embedded version of Dapper in the `ServiceStack.OrmLite.Dapper` namespace has been upgraded to the -latest version of Dapper and also includes Dapper's Async API's in .NET 4.5 builds. - -#### CSV Support for dynamic Dapper results - -The CSV Serializer also added support for Dapper's dynamic results: - -```csharp -IEnumerable results = db.Query("select * from Poco"); -string csv = CsvSerializer.SerializeToCsv(results); -``` - -#### OrmLite CSV Example - -OrmLite avoids `dynamic` and instead prefers the use of code-first POCO's, where the above example translates to: - -```csharp -var results = db.Select(); -var csv = results.ToCsv(); -``` - -To query untyped results in OrmLite when no POCO's exist, you can read them into a generic Dictionary: - -```csharp -var results = db.Select>("select * from Poco"); -var csv = results.ToCsv(); -``` - -### Order By Random - -The new `OrderByRandom()` API abstracts the differences in each RDBMS to return rows in a random order: - -```csharp -var randomRows = db.Select(q => q.OrderByRandom()); -``` - -### Other OrmLite Features - -`CreateTableIfNotExists` returns `true` if a new table was created which is convenient for only populating -non-existing tables with new data on your Application StartUp, e.g: - - ```csharp -if (db.CreateTableIfNotExists()) { - AddSeedData(db); -} - ``` - - - OrmLite Debug Logging includes DB Param names and values - - Char fields now use CHAR(1) - -## [Encrypted Messaging](https://github.com/ServiceStack/ServiceStack/wiki/Encrypted-Messaging) - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/encrypted-messaging.png) - -### Encrypted Messages verified with HMAC SHA-256 - -The authenticity of Encrypted Messages are now being verified with HMAC SHA-256, essentially following an -[Encrypt-then-MAC strategy](http://crypto.stackexchange.com/a/205/25652). The change to the existing process -is that a new AES 256 **Auth Key** is used to Authenticate the encrypted data which is then sent along -with the **Crypt Key**, encrypted with the Server's Public Key. - -An updated version of this process is now: - - 1. Client creates a new `IEncryptedClient` configured with the Server **Public Key** - 2. Client uses the `IEncryptedClient` to create a EncryptedMessage Request DTO: - 1. Generates a new AES 256bit/CBC/PKCS7 Crypt Key **(Kc)**, Auth Key **(Ka)** and **IV** - 2. Encrypts Crypt Key **(Kc)**, Auth Key **(Ka)** with Servers Public Key padded with OAEP = **(Kc+Ka+P)e** - 3. Authenticates **(Kc+Ka+P)e** with **IV** using HMAC SHA-256 = **IV+(Kc+Ka+P)e+Tag** - 4. Serializes Request DTO to JSON packed with current `Timestamp`, `Verb` and `Operation` = **(M)** - 5. Encrypts **(M)** with Crypt Key **(Kc)** and **IV** = **(M)e** - 6. Authenticates **(M)e** with Auth Key **(Ka)** and **IV** = **IV+(M)e+Tag** - 7. Creates `EncryptedMessage` DTO with Servers `KeyId`, **IV+(Kc+Ka+P)e+Tag** and **IV+(M)e+Tag** - 3. Client uses the `IEncryptedClient` to send the populated `EncryptedMessage` to the remote Server - -On the Server, the `EncryptedMessagingFeature` Request Converter processes the `EncryptedMessage` DTO: - - 1. Uses Private Key identified by **KeyId** or the current Private Key if **KeyId** wasn't provided - 1. Request Converter Extracts **IV+(Kc+Ka+P)e+Tag** into **IV** and **(Kc+Ka+P)e+Tag** - 2. Decrypts **(Kc+Ka+P)e+Tag** with Private Key into **(Kc)** and **(Ka)** - 3. The **IV** is checked against the nonce Cache, verified it's never been used before, then cached - 4. The **IV+(Kc+Ka+P)e+Tag** is verified it hasn't been tampered with using Auth Key **(Ka)** - 5. The **IV+(M)e+Tag** is verified it hasn't been tampered with using Auth Key **(Ka)** - 6. The **IV+(M)e+Tag** is decrypted using Crypt Key **(Kc)** = **(M)** - 7. The **timestamp** is verified it's not older than `EncryptedMessagingFeature.MaxRequestAge` - 8. Any expired nonces are removed. (The **timestamp** and **IV** are used to prevent replay attacks) - 9. The JSON body is deserialized and resulting **Request DTO** returned from the Request Converter - 2. The converted **Request DTO** is executed in ServiceStack's Request Pipeline as normal - 3. The **Response DTO** is picked up by the EncryptedMessagingFeature **Response Converter**: - 1. Any **Cookies** set during the Request are removed - 2. The **Response DTO** is serialized with the **AES Key** and returned in an `EncryptedMessageResponse` - 4. The `IEncryptedClient` decrypts the `EncryptedMessageResponse` with the **AES Key** - 1. The **Response DTO** is extracted and returned to the caller - -### Support for versioning Private Keys with Key Rotations - -Another artifact introduced in the above process was the mention of a new `KeyId`. -This is a human readable string used to identify the Servers Public Key using the first 7 characters -of the Public Key Modulus (visible when viewing the Private Key serialized as XML). -This is automatically sent by `IEncryptedClient` to tell the `EncryptedMessagingFeature` which Private Key -should be used to decrypt the AES Crypt and Auth Keys. - -By supporting multiple private keys, the Encrypted Messaging feature allows the seamless transition to a -new Private Key without affecting existing clients who have yet to adopt the latest Public Key. - -Transitioning to a new Private Key just involves taking the existing Private Key and adding it to the -`FallbackPrivateKeys` collection whilst introducing a new Private Key, e.g: - -```csharp -Plugins.Add(new EncryptedMessagesFeature -{ - PrivateKey = NewPrivateKey, - FallbackPrivateKeys = { - PreviousKey2015, - PreviousKey2014, - }, -}); -``` - -### Why Rotate Private Keys? - -Since anyone who has a copy of the Private Key can decrypt encrypted messages, rotating the private key clients -use limits the amount of exposure an adversary who has managed to get a hold of a compromised private key has. -i.e. if the current Private Key was somehow compromised, an attacker with access to the encrypted -network packets will be able to read each message sent that was encrypted with the compromised private key -up until the Server introduces a new Private Key which clients switches over to. - -## [Swagger UI](https://github.com/ServiceStack/ServiceStack/wiki/Swagger-API) - -The Swagger Metadata backend has been upgraded to support the -[Swagger 1.2 Spec](https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md) - -### Basic Auth added to Swagger UI - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/swagger-basicauth.png) - -Users can call protected Services using the Username and Password fields in Swagger UI. -Swagger sends these credentials with every API request using HTTP Basic Auth, -which can be enabled in your AppHost with: - -```csharp -Plugins.Add(new AuthFeature(..., - new IAuthProvider[] { - new BasicAuthProvider(), //Allow Sign-ins with HTTP Basic Auth - })); -``` - -Alternatively users can login outside of Swagger, to access protected Services in Swagger UI. - -## Auth Info displayed in [Metadata Pages](https://github.com/ServiceStack/ServiceStack/wiki/Metadata-page) - -Metadata pages now label protected Services. On the metadata index page it displays a yellow key next to -each Service requiring Authentication: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/metadata-auth-summary.png) - -Hovering over the key will show which also permissions or roles the Service needs. - -This information is also shown the metadata detail pages which will list which permissions/roles are required (if any), e.g: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/metadata-auth.png) - -## [Java Native Types](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) - -### [Java Functional Utils](https://github.com/mythz/java-linq-examples) - -The Core Java Functional Utils required to run -[C#'s 101 LINQ Samples in Java](https://github.com/mythz/java-linq-examples) -have been added to the **net.servicestack:client** Java package which as its compatible with Java 1.7, -also runs on Android: - -[![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/wikis/java/linq-examples-screenshot.png)](https://github.com/mythz/java-linq-examples) - -Whilst noticeably more verbose than most languages, it enables a functional style of programming that provides -an alternative to imperative programming with mutating collections and eases porting efforts of functional code -which can be mapped to its equivalent core functional method. - -### New TreatTypesAsStrings option - -Due to the [unusual encoding of Guid bytes](http://stackoverflow.com/a/18085116/85785) it may be instead be -preferential to treat Guids as opaque strings so they are easier to compare back to their original C# Guids. -This can be enabled with the new `TreatTypesAsStrings` option: - -``` -/* Options: -... -TreatTypesAsStrings: Guid - -*/ -``` - -Which will emit `String` data types for `Guid` properties that are deserialized back into .NET Guid's as strings. - -## [Swift Native Types](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference) - -All Swift reserved keywords are now escaped, allowing them to be used in DTO's. - -## [Service Clients](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) - -All .NET Service Clients (inc [JsonHttpClient](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client#jsonhttpclient)) -can now be used to send raw `string`, `byte[]` or `Stream` Request bodies in their custom Sync or Async API's, e.g: - -```csharp -string json = "{\"Key\":1}"; -client.Post("/sendraw", json); - -byte[] bytes = json.ToUtf8Bytes(); -client.Put("/sendraw", bytes); - -Stream stream = new MemoryStream(bytes); -await client.PostAsync("/sendraw", stream); -``` - -## Authentication - -### [Community Azure Active Directory Auth Provider](https://github.com/jfoshee/ServiceStack.Authentication.Aad) - -[Jacob Foshee](https://github.com/jfoshee) from the ServiceStack Community has published a -[ServiceStack AuthProvider for Azure Active Directory](https://github.com/jfoshee/ServiceStack.Authentication.Aad). - -To get started, Install it from NuGet with: - - PM> Install-Package ServiceStack.Authentication.Aad - -Then add the `AadAuthProvider` AuthProvider to your `AuthFeature` registration: - -```csharp -Plugins.Add(new AuthFeature(..., - new IAuthProvider[] { - new AadAuthProvider(AppSettings) - }); -``` - -See the docs on the -[Projects Homepage](https://github.com/jfoshee/ServiceStack.Authentication.Aad) -for instructions on how to Configure the Azure Directory OAuth Provider in your applications ``. - -### MaxLoginAttempts - -The `MaxLoginAttempts` feature has been moved out from `OrmLiteAuthRepository` into a global option in the -`AuthFeature` plugin where this feature has now been added to all User Auth Repositories. - -E.g. you can lock a User Account after 5 invalid login attempts with: - -```csharp -Plugins.Add(new AuthFeature(...) { - MaxLoginAttempts = 5 -}); -``` - -### Generate New Session Cookies on Authentication - -Previously the Authentication provider only removed Users Cookies after they explicitly log out. -The AuthFeature now also regenerates new Session Cookies each time users login. -If you were previously relying on the user maintaining the same cookies -(i.e. tracking anonymous user activity) this behavior can be disabled with: - -```csharp -Plugins.Add(new AuthFeature(...) { - GenerateNewSessionCookiesOnAuthentication = false -}); -``` - -### ClientId and ClientSecret OAuth Config Aliases - -OAuth Providers can now use `ClientId` and `ClientSecret` aliases instead of `ConsumerKey` and `ConsumerSecret`, e.g: - -```xml - - - - -``` - -## [Error Handling](https://github.com/ServiceStack/ServiceStack/wiki/Error-Handling) - -### Custom Response Error Codes - -In addition to customizing the HTTP Response Body of C# Exceptions with -[IResponseStatusConvertible](https://github.com/ServiceStack/ServiceStack/wiki/Error-Handling#implementing-iresponsestatusconvertible), -you can also customize the HTTP Status Code by implementing `IHasStatusCode`: - -```csharp -public class Custom401Exception : Exception, IHasStatusCode -{ - public int StatusCode - { - get { return 401; } - } -} -``` - -Which is a more cohesive alternative that registering the equivalent -[StatusCode Mapping](https://github.com/ServiceStack/ServiceStack/wiki/Error-Handling#custom-mapping-of-c-exceptions-to-http-error-status): - -```csharp -SetConfig(new HostConfig { - MapExceptionToStatusCode = { - { typeof(Custom401Exception), 401 }, - } -}); -``` - -### Meta Dictionary on ResponseStatus and ResponseError - -The [IMeta](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/IMeta.cs) -Dictionary has been added to `ResponseStatus` and `ResponseError` DTO's which provides a placeholder to -be able to send additional context with errors. - -This Meta dictionary will be automatically populated for any `CustomState` on FluentValidation `ValidationFailure` -that's populated with a `Dictionary`. - -## [Server Events](https://github.com/ServiceStack/ServiceStack/wiki/Server-Events) - -The new `ServerEventsFeature.HouseKeepingInterval` option controls the minimum interval for how often SSE -connections should be routinely scanned and expired subscriptions removed. The default is every 5 seconds. - -> As there's no background Thread managing SSE connections, the cleanup happens in periodic SSE heartbeat handlers - -Update: An [issue with this feature](https://github.com/ServiceStack/Issues/issues/345) has been resolved -in the [v4.0.45 pre-release NuGet packages on MyGet](https://github.com/ServiceStack/ServiceStack/wiki/MyGet). - -## ServiceStack.Text - -There are new convenient extension methods for Converting any POCO to and from Object Dictionary, e.g: - -```csharp -var dto = new User -{ - FirstName = "First", - LastName = "Last", - Car = new Car { Age = 10, Name = "ZCar" }, -}; - -Dictionary map = dtoUser.ToObjectDictionary(); - -User user = (User)map.FromObjectDictionary(typeof(User)); -``` - -Like most Reflection API's in ServiceStack this is fairly efficient as it uses cached compiled delegates. - -There's also an extension method for adding types to `List`, e.g: - -```csharp -var types = new List() - .Add() - .Add(); -``` - -Which is a cleaner equivalent to: - -```csharp -var types = new List(); -types.Add(typeof(User)); -types.Add(typeof(User)); -``` - -# v4.0.42 Release Notes - -## New JsonHttpClient! - -The new `JsonHttpClient` is an alternative to the existing generic typed `JsonServiceClient` for consuming ServiceStack Services -which instead of `HttpWebRequest` is based on Microsoft's latest async `HttpClient` (from [Microsoft.Net.Http](https://www.nuget.org/packages/Microsoft.Net.Http) on NuGet). - -`JsonHttpClient` implements the full [IServiceClient API](https://gist.github.com/mythz/4683438240820b522d39) making it an easy drop-in replacement for your existing `JsonServiceClient` -where in most cases it can simply be renamed to `JsonHttpClient`, e.g: - -```csharp -//IServiceClient client = new JsonServiceClient("http://techstacks.io"); -IServiceClient client = new JsonHttpClient("http://techstacks.io"); -``` - -Which can then be [used as normal](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client): - -```csharp -var response = await client.GetAsync(new GetTechnology { Slug = "servicestack" }); -``` - -### Install - -JsonHttpClient can be downloaded from NuGet at: - - > Install-Package ServiceStack.HttpClient - -### PCL Support - -JsonHttpClient also comes in PCL flavour and can be used on the same platforms as the -[existing PCL Service Clients](https://github.com/ServiceStackApps/HelloMobile) enabling the same clean and productive development experience on popular mobile platforms like -[Xamarin.iOS](http://developer.xamarin.com/guides/ios/) and [Xamarin.Android](http://developer.xamarin.com/guides/android/). - -### [ModernHttpClient](https://github.com/paulcbetts/ModernHttpClient) - -One of the primary benefits of being based on `HttpClient` is being able to make use of -[ModernHttpClient](https://github.com/paulcbetts/ModernHttpClient) which provides a thin wrapper around iOS's native `NSURLSession` or `OkHttp` client on Android, offering improved stability for 3G mobile connectivity. - -To enable, install [ModernHttpClient](https://www.nuget.org/packages/ModernHttpClient) then set the -Global HttpMessageHandler Factory to configure all `JsonHttpClient` instances to use ModernHttpClient's `NativeMessageHandler`: - -```csharp -JsonHttpClient.GlobalHttpMessageHandlerFactory = () => new NativeMessageHandler(); -``` - -Alternatively, you can configure a single client instance to use ModernHttpClient with: - -```csharp -client.HttpMessageHandler = new NativeMessageHandler(); -``` - -### Differences with JsonServiceClient - -Whilst our goal is to retain the same behavior in both clients, there are some differences resulting from using HttpClient where the Global and Instance Request and Response Filters are instead passed HttpClients `HttpRequestMessage` and `HttpResponseMessage`. - -Also, all API's are **Async** under-the-hood where any Sync API's that doesn't return a `Task` just blocks on the Async `Task.Result` response. As this can dead-lock in certain environments we recommend sticking with the Async API's unless safe to do otherwise. - -## Encrypted Messaging! - -One of the benefits of adopting a message-based design is being able to easily layer functionality and generically add value to all Services, we've seen this recently with [Auto Batched Requests](https://github.com/ServiceStack/ServiceStack/wiki/Auto-Batched-Requests) which automatically enables each Service to be batched and executed in a single HTTP Request. Similarly the new Encrypted Messaging feature -enables a secure channel for all Services (inc Auto Batched Requests :) offering protection to clients who can now easily send and receive encrypted messages over unsecured HTTP! - -### Encrypted Messaging Overview - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/encrypted-messaging.png) - -### Configuration - -Encrypted Messaging support is enabled by registering the plugin: - -```csharp -Plugins.Add(new EncryptedMessagesFeature { - PrivateKeyXml = ServerRsaPrivateKeyXml -}); -``` - -Where `PrivateKeyXml` is the Servers RSA Private Key Serialized as XML. If you don't have an existing one, a new one can be generated with: - -```csharp -var rsaKeyPair = RsaUtils.CreatePublicAndPrivateKeyPair(); -string ServerRsaPrivateKeyXml = rsaKeyPair.PrivateKey; -``` - -Once generated, it's important the Private Key is kept confidential as anyone with access will be able to decrypt -the encrypted messages! Whilst most [obfuscation efforts are ultimately futile](http://stackoverflow.com/a/6018247/85785) the goal should be to contain the private key to your running Web Application, limiting access as much as possible. - -Once registered, the EncryptedMessagesFeature enables the 2 Services below: - - - `GetPublicKey` - Returns the Serialized XML of your Public Key (extracted from the configured Private Key) - - `EncryptedMessage` - The Request DTO which encapsulates all encrypted Requests (can't be called directly) - -### Giving Clients the Public Key - -To communicate clients need access to the Server's Public Key, it doesn't matter who has accessed the Public Key only that clients use the **real** Servers Public Key. It's therefore not advisable to download the Public Key over unsecure `http://` where traffic can potentially be intercepted and the key spoofed, subjecting them to a [Man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). - -It's safer instead to download the public key over a trusted `https://` url where the servers origin is verified by a trusted [CA](https://en.wikipedia.org/wiki/Certificate_authority). Sharing the Public Key over Dropbox, Google Drive, OneDrive or other encrypted channels are also good options. - -Since `GetPublicKey` is just a ServiceStack Service it's easily downloadable using a Service Client: - -```csharp -var client = new JsonServiceClient(BaseUrl); -string publicKeyXml = client.Get(new GetPublicKey()); -``` - -If the registered `EncryptedMessagesFeature.PublicKeyPath` has been changed from its default `/publickey`, it can be dowloaded with: - -```csharp -string publicKeyXml = client.Get("/custom-publickey"); // or with HttpUtils: -string publicKeyXml = BaseUrl.CombineWith("/custom-publickey").GetStringFromUrl(); -``` - -> To help with verification the SHA256 Hash of the PublicKey is returned in `X-PublicKey-Hash` HTTP Header - -### Encrypted Service Client - -Once they have the Server's Public Key, clients can use it to get an `EncryptedServiceClient` via the `GetEncryptedClient()` extension method on `JsonServiceClient` or new `JsonHttpClient`, e.g: - -```csharp -var client = new JsonServiceClient(BaseUrl); -IEncryptedClient encryptedClient = client.GetEncryptedClient(publicKeyXml); -``` - -Once configured, clients have access to the familiar typed Service Client API's and productive workflow they're used to with the generic Service Clients, sending typed Request DTO's and returning the typed Response DTO's - rendering the underlying encrypted messages a transparent implementation detail: - -```csharp -HelloResponse response = encryptedClient.Send(new Hello { Name = "World" }); -response.Result.Print(); //Hello, World! -``` - -REST Services Example: - -```csharp -HelloResponse response = encryptedClient.Get(new Hello { Name = "World" }); -``` - -Auto-Batched Requests Example: - -```csharp -var requests = new[] { "Foo", "Bar", "Baz" }.Map(x => new HelloSecure { Name = x }); -var responses = encryptedClient.SendAll(requests); -``` - -When using the `IEncryptedClient`, the entire Request and Response bodies are encrypted including Exceptions which continue to throw a populated `WebServiceException`: - -```csharp -try -{ - var response = encryptedClient.Send(new Hello()); -} -catch (WebServiceException ex) -{ - ex.ResponseStatus.ErrorCode.Print(); //= ArgumentNullException - ex.ResponseStatus.Message.Print(); //= Value cannot be null. Parameter name: Name -} -``` - -### Authentication with Encrypted Messaging - -Many encrypted messaging solutions use Client Certificates which Servers can use to cryptographically verify a client's identity - providing an alternative to HTTP-based Authentication. We've decided against using this as it would've forced an opinionated implementation and increased burden of PKI certificate management and configuration onto Clients and Servers - reducing the applicability and instant utility of this feature. - -We can instead leverage the existing Session-based Authentication Model in ServiceStack letting clients continue to use the existing Auth functionality and Auth Providers they're already used to, e.g: - -```csharp -var authResponse = encryptedClient.Send(new Authenticate { - provider = CredentialsAuthProvider.Name, - UserName = "test@gmail.com", - Password = "p@55w0rd", -}); -``` - -Encrypted Messages have their cookies stripped so they're no longer visible in the clear which minimizes their exposure to Session hijacking. This does pose the problem of how we can call authenticated Services if the encrypted HTTP Client is no longer sending Session Cookies? - -Without the use of clear-text Cookies or HTTP Headers there's no longer an *established Authenticated Session* for the `encryptedClient` to use to make subsequent Authenticated requests. What we can do instead is pass the Session Id in the encrypted body for Request DTO's that implement the new `IHasSessionId` interface, e.g: - -```csharp -[Authenticate] -public class HelloAuthenticated : IReturn, IHasSessionId -{ - public string SessionId { get; set; } - public string Name { get; set; } -} - -var response = encryptedClient.Send(new HelloAuthenticated { - SessionId = authResponse.SessionId, - Name = "World" -}); -``` - -Here we're injecting the returned Authenticated `SessionId` to access the `[Authenticate]` protected Request DTO. However remembering to do this for every authenticated request can get tedious, a nicer alternative is just setting it once on the `encryptedClient` which will then use it to automatically populate any `IHasSessionId` Request DTO's: - -```csharp -encryptedClient.SessionId = authResponse.SessionId; - -var response = encryptedClient.Send(new HelloAuthenticated { - Name = "World" -}); -``` - -> Incidentally this feature is now supported in **all Service Clients** - -### Combined Authentication Strategy - -Another potential use-case is to only use Encrypted Messaging when sending any sensitive information and the normal Service Client for other requests. In which case we can Authenticate and send the user's password with the `encryptedClient`: - -```csharp -var authResponse = encryptedClient.Send(new Authenticate { - provider = CredentialsAuthProvider.Name, - UserName = "test@gmail.com", - Password = "p@55w0rd", -}); -``` - -But then fallback to using the normal `IServiceClient` for subsequent requests. But as the `encryptedClient` doesn't receive cookies we'd need to set it explicitly on the client ourselves with: - -```csharp -client.SetCookie("ss-id", authResponse.SessionId); -``` - -After which the ServiceClient "establishes an authenticated session" and can be used to make Authenticated requests, e.g: - -```csharp -var response = await client.GetAsync(new HelloAuthenticated { Name = "World" }); -``` - -> Note: EncryptedServiceClient is unavailable in PCL Clients - -### [Hybrid Encryption Scheme](https://en.wikipedia.org/wiki/Hybrid_cryptosystem) - -The Encrypted Messaging Feature follows a [Hybrid Cryptosystem](https://en.wikipedia.org/wiki/Hybrid_cryptosystem) which uses RSA Public Keys for [Asymmetric Encryption](https://en.wikipedia.org/wiki/Public-key_cryptography) combined with the performance of AES [Symmetric Encryption](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) making it suitable for encrypting large message payloads. - -The key steps in the process are outlined below: - - 1. The Client creates a new `IEncryptedClient` configured with the Server **Public Key** - 2. The Client uses the `IEncryptedClient` to send a Request DTO: - 1. A new 256-bit Symmetric **AES Key** and [IV](https://en.wikipedia.org/wiki/Initialization_vector) is generated - 2. The **AES Key** and **IV** bytes are merged, encrypted with the Servers **Public Key** and Base64 encoded - 3. The Request DTO is serialized into JSON and packed with the current **Timestamp**, **Verb** and **Operation** and encrypted with the new **AES Key** - 3. The `IEncryptedClient` uses the underlying JSON Service Client to send the `EncryptedMessage` to the remote Server - 4. The `EncryptedMessage` is picked up and decrypted by the EncryptedMessagingFeature **Request Converter**: - 1. The **AES Key** is decrypted with the Servers **Private Key** - 2. The **IV** is checked against the nonce Cache, verified it's never been used before, then cached - 3. The unencrypted **AES Key** is used to decrypt the **EncryptedBody** - 4. The **timestamp** is verified it's not older than `EncryptedMessagingFeature.MaxRequestAge` - 5. Any expired nonces are removed. (The **timestamp** and **IV** are used to prevent replay attacks) - 6. The JSON body is deserialized and resulting **Request DTO** returned from the Request Converter - 5. The converted **Request DTO** is executed in ServiceStack's Request Pipeline as normal - 6. The **Response DTO** is picked up by the EncryptedMessagingFeature **Response Converter**: - 1. Any **Cookies** set during the Request are removed - 2. The **Response DTO** is serialized with the **AES Key** and returned in an `EncryptedMessageResponse` - 7. The `IEncryptedClient` decrypts the `EncryptedMessageResponse` with the **AES Key** - 1. The **Response DTO** is extracted and returned to the caller - -A visual of how this all fits together in captured in the high-level diagram below: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/encrypted-messaging.png) - - - Components in **Yellow** show the encapsulated Encrypted Messaging functionality where all encryption and decryption is performed - - Components in **Blue** show Unencrypted DTO's - - Components in **Green** show Encrypted content: - - The AES Key and IV in **Dark Green** is encrypted by the client using the Server's Public Key - - The EncryptedRequest in **Light Green** is encrypted with a new AES Key generated by the client on each Request - - Components in **Dark Grey** depict existing ServiceStack functionality where Requests are executed as normal through the [Service Client](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) and [Request Pipeline](https://github.com/ServiceStack/ServiceStack/wiki/Order-of-Operations) - -All Request and Response DTO's get encrypted and embedded in the `EncryptedMessage` and `EncryptedMessageResponse` DTO's below: - -```csharp -public class EncryptedMessage : IReturn -{ - public string EncryptedSymmetricKey { get; set; } - public string EncryptedBody { get; set; } -} - -public class EncryptedMessageResponse -{ - public string EncryptedBody { get; set; } -} -``` - -The diagram also expands the `EncryptedBody` Content containing the **EncryptedRequest** consisting of the following parts: - - - **Timestamp** - Unix Timestamp of the Request - - **Verb** - Target HTTP Method - - **Operation** - Request DTO Name - - **JSON** - Request DTO serialized as JSON - -### Source Code - - - The Client implementation is available in [EncryptedServiceClient.cs](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Client/EncryptedServiceClient.cs) - - The Server implementation is available in [EncryptedMessagesFeature.cs](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/EncryptedMessagesFeature.cs) - - The Crypto Utils used are available in the [RsaUtils.cs](https://github.com/ServiceStack/ServiceStack/blob/b4a2a1f74936c8a100b688cbdbca08ff5b212cbe/src/ServiceStack.Client/CryptUtils.cs#L31) and [AesUtils.cs](https://github.com/ServiceStack/ServiceStack/blob/b4a2a1f74936c8a100b688cbdbca08ff5b212cbe/src/ServiceStack.Client/CryptUtils.cs#L189) - - Tests are available in [EncryptedMessagesTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/UseCases/EncryptedMessagesTests.cs) - -## Request and Response Converters - -The Encrypted Messaging Feature takes advantage of new Converters that let you change the Request DTO and Response DTO's that get used in ServiceStack's Request Pipeline where: - -Request Converters are executed directly after any [Custom Request Binders](https://github.com/ServiceStack/ServiceStack/wiki/Serialization-deserialization#create-a-custom-request-dto-binder): - -```csharp -appHost.RequestConverters.Add((req, requestDto) => { - //Return alternative Request DTO or null to retain existing DTO -}); -``` - -Response Converters are executed directly after the Service: - -```csharp -appHost.ResponseConverters.Add((req, response) => - //Return alternative Response or null to retain existing Service response -}); -``` - -In addition to the converters above, Plugins can now register new callbacks in `IAppHost.OnEndRequestCallbacks` which gets fired at the end of a request. - -## [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) - -### Eclipse Integration! - -We've further expanded our support for Java with our new **ServiceStackEclipse** plugin providing cross-platform [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) integration with Eclipse on Windows, OSX and Linux! - -#### Install from Eclipse Marketplace - -To install, search for **ServiceStack** in the Eclipse Marketplace at `Help > Eclipse Marketplace`: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackeclipse/ss-eclipse-install-win.gif) - -Find the **ServiceStackEclipse** plugin, click **Install** and follow the wizard to the end, restarting to launch Eclipse with the plugin loaded! - -> **ServiceStackEclipse** is best used with Java Maven Projects where it automatically adds the **ServiceStack.Java** client library to your Maven Dependencies and when your project is set to **Build Automatically**, are then downloaded and registered, so you're ready to start consuming ServiceStack Services with the new `JsonServiceClient`! - -#### Eclipse Add ServiceStack Reference - -Just like Android Studio you can right-click on a Java Package to open the **Add ServiceStack Reference...** dialog from the Context Menu: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackeclipse/add-reference-demo.gif) - -Complete the dialog to add the remote Servers generated Java DTO's to your selected Java package and the `net.servicestack.client` dependency to your Maven dependencies. - -#### Eclipse Update ServiceStack Reference - -Updating a ServiceStack Reference works as normal where you can change any of the available options in the header comments, save, then right-click on the file in the File Explorer and click on **Update ServiceStack Reference** in the Context Menu: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackeclipse/update-reference-demo.gif) - -### ServiceStack IDEA IntelliJ Plugin - -The **ServiceStackIDEA** plugin has added support for IntelliJ Maven projects giving Java devs a productive and familiar development experience whether they're creating Android Apps or pure cross-platform Java clients. - -#### Install ServiceStack IDEA from the Plugin repository - -The ServiceStack IDEA is now available to install directly from within IntelliJ or Android Studio IDE Plugins Repository, to Install Go to: - - 1. `File -> Settings...` Main Menu Item - 2. Select **Plugins** on left menu then click **Browse repositories...** at bottom - 3. Search for **ServiceStack** and click **Install plugin** - 4. Restart to load the installed ServiceStack IDEA plugin - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackidea/android-plugin-download.gif) - -### ssutil.exe - Command line ServiceStack Reference tool - -Add ServiceStack Reference is also moving beyond our growing list of supported IDEs and is now available in a single cross-platform .NET command-line **.exe** making it easy for build servers and automated tasks or command-line runners of your favorite text editors to easily Add and Update ServiceStack References! - -To Get Started download **ssutil.exe** and open a command prompt to the containing directory: - -#### Download [ssutil.exe](https://github.com/ServiceStack/ServiceStackVS/raw/master/dist/ssutil.exe) - -#### ssutil.exe Usage: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackvs/ssutil-help.png) - -**Adding a new ServiceStack Reference** - -To create a new ServiceStack Reference, pass the remote ServiceStack **BaseUrl** then specify both which `-file` and `-lang` you want, e.g: - - ssutil http://techstacks.io -file TechStacks -lang CSharp - -Executing the above command fetches the C# DTOs and saves them in a local file named `TechStacks.dtos.cs`. - -**Available Languages** - - - CSharp - - FSharp - - VbNet - - Java - - Swift - - TypeScript.d - -**Update existing ServiceStack Reference** - -Updating a ServiceStack Reference is even easier we just specify the path to the existing generated DTO's. E.g. Update the `TechStacks.dtos.cs` we just created with: - - ssutil TechStacks.dtos.cs - -### [Using Xamarin.Auth with ServiceStack](https://github.com/ServiceStackApps/TechStacksAuth) - -[Xamarin.Auth](https://components.xamarin.com/gettingstarted/xamarin.auth) -is an extensible Component and provides a good base for handling authenticating with ServiceStack from Xamarin platforms. To show how to make use of it we've created the [TechStacksAuth](https://github.com/ServiceStackApps/TechStacksAuth) example repository containing a custom `WebAuthenticator` we use to call our remote ServiceStack Web Application and reuse its existing OAuth integration. - -Here's an example using `TwitterAuthProvider`: - -![](https://github.com/ServiceStack/Assets/raw/master/img/apps/TechStacks/xamarin-android-auth-demo.gif) - -Checkout the [TechStacksAuth](https://github.com/ServiceStackApps/TechStacksAuth) repo for the docs and source code. - -### Swift - -Unfortunately the recent release of Xcode 6.4 and Swift 1.2 still haven't fixed the [earlier regression added in Xcode 6.3 and Swift 1.2](https://github.com/ServiceStack/ServiceStack/blob/master/docs/2015/release-notes.md#swift-native-types-upgraded-to-swift-12) where the Swift compiler segfaults trying to compile Extensions to Types with a Generic Base Class. The [swift-compiler-crashes](https://github.com/practicalswift/swift-compiler-crashes) repository is reporting this is now fixed in Swift 2.0 / Xcode 7 beta but as that wont be due till later this year we've decided to improve the experience by not generating any types with the problematic Generic Base Types from the generated DTO's by default. This is configurable with: - -```swift -//ExcludeGenericBaseTypes: True -``` - -Any types that were omitted from the generated DTO's will be emitted in comments, using the format: - -```swift -//Excluded: {TypeName} -``` - -### C#, F#, VB.NET Service Reference - -The C#, F# and VB.NET Native Type providers can emit `[GeneratedCode]` attributes with: - -```csharp -AddGeneratedCodeAttributes: True -``` - -This is useful for skipping any internal Style Cop rules on generated code. - -## Service Clients - -### Custom Client Caching Strategy - -New `ResultsFilter` and `ResultsFilterResponse` delegates have been added to all Service Clients allowing clients to employ a custom caching strategy. - -Here's a basic example implementing a cache for all **GET** Requests: - -```csharp -var cache = new Dictionary(); - -client.ResultsFilter = (type, method, uri, request) => { - if (method != HttpMethods.Get) return null; - object cachedResponse; - cache.TryGetValue(uri, out cachedResponse); - return cachedResponse; -}; -client.ResultsFilterResponse = (webRes, response, method, uri, request) => { - if (method != HttpMethods.Get) return; - cache[uri] = response; -}; - -//Subsequent requests returns cached result -var response1 = client.Get(new GetCustomer { CustomerId = 5 }); -var response2 = client.Get(new GetCustomer { CustomerId = 5 }); //cached response -``` - -The `ResultsFilter` delegate is executed with the context of the request before the request is made. Returning a value of type `TResponse` short-circuits the request and returns that response. Otherwise the request continues and its response passed into the `ResultsFilterResponse` delegate where it can be cached. - -#### New ServiceClient API's - -The following new API's were added to all .NET Service Clients: - - - `SetCookie()` - Sets a Cookie on the clients `CookieContainer` - - `GetCookieValues()` - Return all site Cookies in a string Dictionary - - `CustomMethodAsync()` - Call any Custom HTTP Method Asynchronously - -### Implicit Versioning - -Similar to the behavior of `IHasSessionId` above, Service Clients that have specified a `Version` number, e.g: - -```csharp -client.Version = 2; -``` - -Will populate that version number in all Request DTO's implementing `IHasVersion`, e.g: - -```csharp -public class Hello : IReturn, IHasVersion { - public int Version { get; set; } - public string Name { get; set; } -} - -client.Version = 2; -client.Get(new Hello { Name = "World" }); // Hello.Version=2 -``` - -#### Version Abbreviation Convention - -A popular convention for specifying versions in API requests is with the `?v=1` QueryString which ServiceStack now uses as a fallback for populating any Request DTO's that implement `IHasVersion` (as above). - -> Note: as ServiceStack's message-based design promotes forward and backwards-compatible Service API designs, our recommendation is to only consider implementing versioning when necessary, at which point check out our [recommended versioning strategy](http://stackoverflow.com/a/12413091/85785). - -## Cancellable Requests Feature - -The new Cancellable Requests Feature makes it easy to design long-running Services that are cancellable with an external Web Service Request. To enable this feature, register the `CancellableRequestsFeature` plugin: - -```csharp -Plugins.Add(new CancellableRequestsFeature()); -``` - -### Designing a Cancellable Service - -Then in your Service you can wrap your implementation within a disposable `ICancellableRequest` block which encapsulates a Cancellation Token that you can watch to determine if the Request has been cancelled, e.g: - -```csharp -public object Any(TestCancelRequest req) -{ - using (var cancellableRequest = base.Request.CreateCancellableRequest()) - { - //Simulate long-running request - while (true) - { - cancellableRequest.Token.ThrowIfCancellationRequested(); - Thread.Sleep(100); - } - } -} -``` - -### Cancelling a remote Service - -To be able to cancel a Server request on the client, the client must first **Tag** the request which it does by assigning the `X-Tag` HTTP Header with a user-defined string in a Request Filter before calling a cancellable Service, e.g: - -```csharp -var tag = Guid.NewGuid().ToString(); -var client = new JsonServiceClient(baseUri) { - RequestFilter = req => req.Headers[HttpHeaders.XTag] = tag -}; - -var responseTask = client.PostAsync(new TestCancelRequest()); -``` - -Then at anytime whilst the Service is still executing the remote request can be cancelled by calling the `CancelRequest` Service with the specified **Tag**, e.g: - -```csharp -var cancelResponse = client.Post(new CancelRequest { Tag = tag }); -``` - -If it was successfully cancelled it will return a `CancelRequestResponse` DTO with the elapsed time of how long the Service ran for. Otherwise if the remote Service had completed or never existed it will throw **404 Not Found** in a `WebServiceException`. - -## Include Aggregates in AutoQuery - -AutoQuery now supports running additional Aggregate queries on the queried result-set. -To include aggregates in your Query's response specify them in the `Include` property of your AutoQuery Request DTO, e.g: - - var response = client.Get(new Query Rockstars { Include = "COUNT(*)" }) - -Or in the `Include` QueryString param if you're calling AutoQuery Services from a browser, e.g: - - /rockstars?include=COUNT(*) - -The result is then published in the `QueryResponse.Meta` String Dictionary and is accessible with: - - response.Meta["COUNT(*)"] //= 7 - -By default any of the functions in the SQL Aggregate whitelist can be referenced: - - AVG, COUNT, FIRST, LAST, MAX, MIN, SUM - -Which can be added to or removed from by modifying `SqlAggregateFunctions` collection, e.g, you can allow usage of a `CustomAggregate` SQL Function with: - - Plugins.Add(new AutoQueryFeature { - SqlAggregateFunctions = { "CustomAggregate" } - }) - -### Aggregate Query Usage - -The syntax for aggregate functions is modelled after their usage in SQL so they should be instantly familiar. -At its most basic usage you can just specify the name of the aggregate function which will use `*` as a default argument so you can also query `COUNT(*)` with: - - ?include=COUNT - -It also supports SQL aliases: - - COUNT(*) Total - COUNT(*) as Total - -Which is used to change what key the result is saved into: - - response.Meta["Total"] - -Columns can be referenced by name: - - COUNT(LivingStatus) - -If an argument matches a column in the primary table the literal reference is used as-is, if it matches a column in a joined table it's replaced with its fully-qualified reference and when it doesn't match any column, Numbers are passed as-is otherwise its automatically escaped and quoted and passed in as a string literal. - -The `DISTINCT` modifier can also be used, so a complex example looks like: - - COUNT(DISTINCT LivingStatus) as UniqueStatus - -Which saves the result of the above function in: - - response.Meta["UniqueStatus"] - -Any number of aggregate functions can be combined in a comma-delimited list: - - Count(*) Total, Min(Age), AVG(Age) AverageAge - -Which returns results in: - - response.Meta["Total"] - response.Meta["Min(Age)"] - response.Meta["AverageAge"] - -#### Aggregate Query Performance - -Surprisingly AutoQuery is able to execute any number of Aggregate functions without performing any additional queries as previously to support paging, a `Total` needed to be executed for each AutoQuery. Now the `Total` query is combined with all other aggregate functions and executed in a single query. - -### AutoQuery Response Filters - -The Aggregate functions feature is built on the new `ResponseFilters` support in AutoQuery which provides a new extensibility option enabling customization and additional metadata to be attached to AutoQuery Responses. As the Aggregate Functions support is itself a Response Filter in can disabled by clearing them: - -```csharp -Plugins.Add(new AutoQueryFeature { - ResponseFilters = new List>() -}) -``` - -The Response Filters are executed after each AutoQuery and gets passed the full context of the executed query, i.e: - -```csharp -class QueryFilterContext -{ - IDbConnection Db // The ADO.NET DB Connection - List Commands // Tokenized list of commands - IQuery Request // The AutoQuery Request DTO - ISqlExpression SqlExpression // The AutoQuery SqlExpression - IQueryResponse Response // The AutoQuery Response DTO -} -``` - -Where the `Commands` property contains the parsed list of commands from the `Include` property, tokenized into the structure below: - -```csharp -class Command -{ - string Name - List Args - string Suffix -} -``` - -With this we could add basic calculator functionality to AutoQuery with the custom Response Filter below: - -```csharp -Plugins.Add(new AutoQueryFeature { - ResponseFilters = { - ctx => { - var supportedFns = new Dictionary>(StringComparer.OrdinalIgnoreCase) - { - {"ADD", (a,b) => a + b }, - {"MULTIPLY", (a,b) => a * b }, - {"DIVIDE", (a,b) => a / b }, - {"SUBTRACT", (a,b) => a - b }, - }; - var executedCmds = new List(); - foreach (var cmd in ctx.Commands) - { - Func fn; - if (!supportedFns.TryGetValue(cmd.Name, out fn)) continue; - var label = !string.IsNullOrWhiteSpace(cmd.Suffix) ? cmd.Suffix.Trim() : cmd.ToString(); - ctx.Response.Meta[label] = fn(int.Parse(cmd.Args[0]), int.Parse(cmd.Args[1])).ToString(); - executedCmds.Add(cmd); - } - ctx.Commands.RemoveAll(executedCmds.Contains); - } - } -}) -``` - -Which now lets users perform multiple basic arithmetic operations with any AutoQuery request! - -```csharp -var response = client.Get(new QueryRockstars { - Include = "ADD(6,2), Multiply(6,2) SixTimesTwo, Subtract(6,2), divide(6,2) TheDivide" -}); - -response.Meta["ADD(6,2)"] //= 8 -response.Meta["SixTimesTwo"] //= 12 -response.Meta["Subtract(6,2)"] //= 4 -response.Meta["TheDivide"] //= 3 -``` - -### Untyped SqlExpression - -If you need to introspect or modify the executed `ISqlExpression`, it’s useful to access it as a `IUntypedSqlExpression` so its non-generic API's are still accessible without having to convert it back into its concrete generic `SqlExpression` Type, e.g: - -```csharp -IUntypedSqlExpression q = ctx.SqlExpression.GetUntypedSqlExpression() - .Clone(); -``` - -> Cloning the SqlExpression allows you to modify a copy that won't affect any other Response Filter. - -### AutoQuery Property Mapping - -AutoQuery can map `[DataMember]` property aliases on Request DTO's to the queried table, e.g: - -```csharp -public class QueryPerson : QueryBase -{ - [DataMember("first_name")] - public string FirstName { get; set; } -} - -public class Person -{ - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } -} -``` - -Which can be queried with: - - ?first_name=Jimi - -or by setting the global `JsConfig.EmitLowercaseUnderscoreNames=true` convention: - -```csharp -public class QueryPerson : QueryBase -{ - public string LastName { get; set; } -} -``` - -Where it's also queryable with: - - ?last_name=Hendrix - -## OrmLite - -### Dynamic Result Sets - -There's new support for returning unstructured resultsets letting you Select `List` instead of having results mapped to a concrete Poco class, e.g: - -```csharp -db.Select>(db.From() - .Select("COUNT(*), MIN(Id), MAX(Id)"))[0].PrintDump(); -``` - -Output of objects in the returned `List`: - - [ - 10, - 1, - 10 - ] - -You can also Select `Dictionary` to return a dictionary of column names mapped with their values, e.g: - -```csharp -db.Select>(db.From() - .Select("COUNT(*) Total, MIN(Id) MinId, MAX(Id) MaxId"))[0].PrintDump(); -``` - -Output of objects in the returned `Dictionary`: - - { - Total: 10, - MinId: 1, - MaxId: 10 - } - -and can be used for API's returning a **Single** row result: - -```csharp -db.Single>(db.From() - .Select("COUNT(*) Total, MIN(Id) MinId, MAX(Id) MaxId")).PrintDump(); -``` - -or use `object` to fetch an unknown **Scalar** value: - -```csharp -object result = db.Scalar(db.From().Select(x => x.Id)); -``` - -### New DB Parameters API's - -To enable even finer-grained control of parameterized queries we've added new overloads that take a collection of IDbDataParameter's: - -```csharp -List Select(string sql, IEnumerable sqlParams) -T Single(string sql, IEnumerable sqlParams) -T Scalar(string sql, IEnumerable sqlParams) -List Column(string sql, IEnumerable sqlParams) -IEnumerable ColumnLazy(string sql, IEnumerable sqlParams) -HashSet ColumnDistinct(string sql, IEnumerable sqlParams) -Dictionary> Lookup(string sql, IEnumerable sqlParams) -List SqlList(string sql, IEnumerable sqlParams) -List SqlColumn(string sql, IEnumerable sqlParams) -T SqlScalar(string sql, IEnumerable sqlParams) -``` - -> Including Async equivalents for each of the above Sync API's. - -The new API's let you execute parameterized SQL with finer-grained control over the `IDbDataParameter` used, e.g: - -```csharp -IDbDataParameter pAge = db.CreateParam("age", 40, dbType:DbType.Int16); -db.Select("SELECT * FROM Person WHERE Age > @pAge", new[] { pAge }); -``` - -The new `CreateParam()` extension method above is a useful helper for creating custom IDbDataParameter's. - -### Customize null values - -The new `OrmLiteConfig.OnDbNullFilter` lets you to replace DBNull values with a custom value, so you could convert all `null` strings to be populated with `"NULL"` using: - -```csharp -OrmLiteConfig.OnDbNullFilter = fieldDef => - fieldDef.FieldType == typeof(string) - ? "NULL" - : null; -``` - -### Case Insensitive References - -If you're using a case-insensitive database you can tell OrmLite to match on case-insensitive POCO references with: - -```csharp -OrmLiteConfig.IsCaseInsensitive = true; -``` - -### Enhanced CaptureSqlFilter - -CaptureSqlFilter now tracks DB Parameters used in each query which can be used to quickly found out what SQL your DB calls generate by surrounding DB access in a using scope like: - -```csharp -using (var captured = new CaptureSqlFilter()) -using (var db = OpenDbConnection()) -{ - db.Where(new { Age = 27 }); - - captured.SqlCommandHistory[0].PrintDump(); -} -``` - -Emits the Executed SQL along with any DB Parameters: - - { - Sql: "SELECT ""Id"", ""FirstName"", ""LastName"", ""Age"" FROM ""Person"" WHERE ""Age"" = @Age", - Parameters: - { - Age: 27 - } - } - -### Other OrmLite Features - - - New `IncludeFunctions = true` T4 Template configuration for generating Table Valued Functions added by [@mikepugh](https://github.com/mikepugh) - - New `OrmLiteConfig.SanitizeFieldNameForParamNameFn` can be used to support sanitizing field names with non-ascii values into legal DB Param names - -## Authentication - -### Enable Session Ids on QueryString - -Setting `Config.AllowSessionIdsInHttpParams=true` will allow clients to specify the `ss-id`, `ss-pid` Session Cookies on the QueryString or FormData. This is useful for getting Authenticated SSE Sessions working in IE9 which needs to rely on SSE Polyfills that's unable to send Cookies or Custom HTTP Headers. - -The [SSE-polyfills Chat Demo](http://chat.servicestack.net/default_ieshim) has an example of adding the Current Session Id on the [JavaScript SSE EventSource Url](https://github.com/ServiceStackApps/Chat/blob/master/src/Chat/default_ieshim.cshtml#L93): - -```js -var source = new EventSource('/event-stream?channels=@channels&ss-id=@(base.GetSession().Id)'); -``` - -### In Process Authenticated Requests - -You can enable the `CredentialsAuthProvider` to allow **In Process** requests to Authenticate without a Password with: - -```csharp -new CredentialsAuthProvider { - SkipPasswordVerificationForInProcessRequests = true, -} -``` - -When enabled this lets **In Process** Service Requests to login as a specified user without needing to provide their password. - -For example this could be used to create an [Intranet Restricted](https://github.com/ServiceStack/ServiceStack/wiki/Restricting-Services) **Admin-Only** Service that lets you login as another user so you can debug their account without knowing their password with: - -```csharp -[RequiredRole("Admin")] -[Restrict(InternalOnly=true)] -public class ImpersonateUser -{ - public string UserName { get; set; } -} - -public object Any(ImpersonateUser request) -{ - using (var service = base.ResolveService()) //In Process - { - return service.Post(new Authenticate { - provider = AuthenticateService.CredentialsProvider, - UserName = request.UserName, - }); - } -} -``` - -> Your Services can use the new `Request.IsInProcessRequest()` to identify Services that were executed in-process. - -### New CustomValidationFilter Filter - -The new `CustomValidationFilter` is available on each `AuthProvider` and can be used to add custom validation logic where returning any non-null response will short-circuit the Auth Process and return the response to the client. - -The Validation Filter receives the full [AuthContext](https://github.com/ServiceStack/ServiceStack/blob/dd938c284ea509c4cdfab0e416c489aae7877981/src/ServiceStack/Auth/AuthProvider.cs#L415-L424) captured about the Authentication Request. - -So if you're under attack you could use this filter to Rick Roll North Korean hackers :) - -```csharp -Plugins.Add(new AuthFeature(..., - new IAuthProvider[] { - new CredentialsAuthProvider { - CustomValidationFilter = authCtx => - authCtx.Request.UserHostAddress.StartsWith("175.45.17") - ? HttpResult.Redirect("https://youtu.be/dQw4w9WgXcQ") - : null - } - })); -``` - -### UserName Validation - -The UserName validation for all Auth Repositories have been consolidated in a central location, configurable at: - -```csharp -Plugins.Add(new AuthFeature(...){ - ValidUserNameRegEx = new Regex(@"^(?=.{3,20}$)([A-Za-z0-9][._-]?)*$", RegexOptions.Compiled), -}) -``` - -> Note: the default UserName RegEx above was increased from 15 chars limit to 20 chars - -Instead of RegEx you can choose to validate using a Custom Predicate. The example below ensures UserNames don't include specific chars: - -```csharp -Plugins.Add(new AuthFeature(...){ - IsValidUsernameFn = userName => userName.IndexOfAny(new[] { '@', '.', ' ' }) == -1 -}) -``` - -### Overridable Hash Provider - -The `IHashProvider` used to generate and verify password hashes and salts in each UserAuth Repository is now overridable from its default with: - -```csharp -container.Register(c => - new SaltedHash(HashAlgorithm:new SHA256Managed(), theSaltLength:4)); -``` - -### Configurable Session Expiry - -Permanent and Temporary Sessions can now be configured separately with different Session Expiries, configurable on either `AuthFeature` or `SessionFeature` plugins, e.g: - -```csharp -new AuthFeature(...) { - SessionExpiry = TimeSpan.FromDays(7 * 2), - PermanentSessionExpiry = TimeSpan.FromDays(7 * 4), -} -``` - -The above defaults configures Temporary Sessions to last a maximum of 2 weeks and Permanent Sessions lasting 4 weeks. - -## Redis - - - New `PopItemsFromSet(setId, count)` API added by [@scottmcarthur](https://github.com/scottmcarthur) - - The `SetEntry()` API's for setting string values in `IRedisClient` have been deprecated in favor of new `SetValue()` API's. - - Large performance improvement for saving large values (>8MB) - - Internal Buffer pool now configurable with `RedisConfig.BufferLength` and `RedisConfig.BufferPoolMaxSize` - -## ServiceStack.Text - - - Use `JsConfig.ExcludeDefaultValues=true` to reduce payloads by omitting properties with default values - - Text serializers now serialize any property or field annotated with the `[DataMember]` attribute, inc. private fields. - - Updated `RecyclableMemoryStream` to the latest version, no longer throws an exception for disposing streams twice - - Added support for serializing collections with base types - -#### T[].NewArray() Usage - -The `NewArray()` extension method reduces boilerplate required in modifying and returning an Array, it's useful when modifying configuration using fixed-size arrays, e.g: - -```csharp -JsConfig.IgnoreAttributesNamed = JsConfig.IgnoreAttributesNamed.NewArray( - with: typeof(ScriptIgnoreAttribute).Name, - without: typeof(JsonIgnoreAttribute).Name); -``` - -Which is equivalent to the imperative alternative: - -```csharp -var attrNames = new List(JsConfig.IgnoreAttributesNamed) { - typeof(ScriptIgnoreAttribute).Name -}; -attrNames.Remove(typeof(JsonIgnoreAttribute).Name)); -JsConfig.IgnoreAttributesNamed = attrNames.ToArray(); -``` - -#### byte[].Combine() Usage - -The `Combine(byte[]...)` extension method combines multiple byte arrays into a single byte[], e.g: - -```csharp -byte[] bytes = "FOO".ToUtf8Bytes().Combine(" BAR".ToUtf8Bytes(), " BAZ".ToUtf8Bytes()); -bytes.FromUtf8Bytes() //= FOO BAR BAZ -``` - -## Swagger - -Swagger support has received a number of fixes and enhancements which now generates default params for DTO properties that aren't attributed with `[ApiMember]` attribute. Specifying a single `[ApiMember]` attribute reverts back to the existing behavior of only showing `[ApiMember]` DTO properties. - -You can now Exclude **properties** from being listed in Swagger when using: - -```csharp -[IgnoreDataMember] -``` - -Exclude **properties** from being listed in Swagger Schema Body with: - -```csharp -[ApiMember(ExcludeInSchema=true)] -``` - -Or exclude entire Services from showing up in Swagger or any other Metadata Services (i.e. Metadata Pages, Postman, NativeTypes, etc) by annotating **Request DTO's** with: - -```csharp -[Exclude(Feature.Metadata)] -``` - -## SOAP - -There's finer-grain control available over which **Operations** and **Types** are exported in SOAP WSDL's and XSD's by overriding the new `ExportSoapOperationTypes()` and `ExportSoapType()` methods in your AppHost. - -You can also exclude specific Request DTO's from being emitted in WSDL's and XSD's with: - -```csharp -[Exclude(Feature.Soap)] -public class HiddenFromSoap { .. } -``` - -You can also override and customize how the SOAP Message Responses are written, here's a basic example: - -```csharp -public override WriteSoapMessage(Message message, Stream outputStream) -{ - using (var writer = XmlWriter.Create(outputStream, Config.XmlWriterSettings)) - { - message.WriteMessage(writer); - } -} -``` - -> The default [WriteSoapMessage](https://github.com/ServiceStack/ServiceStack/blob/fb08f5cb408ece66f203f677a4ec14ee9aad78ae/src/ServiceStack/ServiceStackHost.Runtime.cs#L484) implementation also raises a ServiceException and writes any returned response to a buffered Response Stream (if configured). - -## Minor Enhancements - - - The Validation Features `AbstractValidator` base class now implements `IRequiresRequest` and gets injected with the current Request - - Response DTO is available at `IResponse.Dto` - - Use `IResponse.ClearCookies()` to clear any cookies added during the Request pipeline before their written to the response - - Use `[Exclude(Feature.Metadata)]` to hide Operations from being exposed in Metadata Services, inc. Metadata pages, Swagger, Postman, NativeTypes, etc - - Use new `container.TryResolve(Type)` to resolve dependencies by runtime `Type` - - New `debugEnabled` option added to `InMemoryLog` and `EventLogger` - -### [Simple Customer REST Example](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/CustomerRestExample.cs) - -New stand-alone [Customer REST Example](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/CustomerRestExample.cs) added showing an complete example of creating a Typed Client / Server REST Service with ServiceStack. Overview of this example was [answered on StackOverflow](http://stackoverflow.com/a/30273466/85785). - -## Community - - - [Jacob Foshee](https://twitter.com/82unpluggd) released a [custom short URLs ServiceStack Service](https://github.com/Durwella/UrlShortening) hosted on Azure. - -## Breaking changes - - - The provider ids for `InstagramOAuth2Provider` was renamed to `/auth/instagram` and `MicrosoftLiveOAuth2Provider` was renamed to `/auth/microsoftlive`. - - All API's that return `HttpWebResponse` have been removed from `IServiceClient` and replaced with source-compatible extension methods - - `CryptUtils` have been deprecated and replaced with the more specific `RsaUtils` - - `System.IO.Compression` functionality was removed from the PCL clients to workaround an [issue on Xamarin platforms](https://forums.servicestack.net/t/xamarin-ios-and-servicestack-dependency-issue/803/11) - -All external NuGet packages were upgraded to their most recent major version (as done before every release). - -# 4.0.40 Release Notes - -## Native support for Java and Android Studio! - -In our goal to provide a highly productive and versatile Web Services Framework that's ideal for services-heavy Mobile platforms, Service Oriented Architectures and Single Page Apps we're excited to announce new Native Types support for Java providing a terse and productive strong-typed Java API for the worlds most popular mobile platform - [Android](https://www.android.com/)! - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/release-notes/android-studio-splash.png) - -The new native Java types support for Android significantly enhances [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) support for mobile platforms to provide a productive dev workflow for mobile developers on the primary .NET, iOS and Java IDE's: - - - -#### [VS.NET integration with ServiceStackVS](https://visualstudiogallery.msdn.microsoft.com/5bd40817-0986-444d-a77d-482e43a48da7) - -Providing [C#](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference), [F#](https://github.com/ServiceStack/ServiceStack/wiki/FSharp-Add-ServiceStack-Reference), [VB.NET](https://github.com/ServiceStack/ServiceStack/wiki/VB.Net-Add-ServiceStack-Reference) and [TypeScript](https://github.com/ServiceStack/ServiceStack/wiki/TypeScript-Add-ServiceStack-Reference) Native Types support in Visual Studio for the [most popular platforms](https://github.com/ServiceStackApps/HelloMobile) including iOS and Android using [Xamarin.iOS](https://github.com/ServiceStackApps/HelloMobile#xamarinios-client) and [Xamarin.Android](https://github.com/ServiceStackApps/HelloMobile#xamarinandroid-client) on Windows. - -#### [Xamarin Studio integration with ServiceStackXS](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference#xamarin-studio) - -Providing [C# Native Types](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference) support for developing iOS and Android mobile Apps using [Xamarin.iOS](https://github.com/ServiceStackApps/HelloMobile#xamarinios-client) and [Xamarin.Android](https://github.com/ServiceStackApps/HelloMobile#xamarinandroid-client) with [Xamarin Studio](http://xamarin.com/studio) on OSX. The **ServiceStackXS** plugin also provides a rich web service development experience developing Client applications with [Mono Develop on Linux](https://github.com/ServiceStack/ServiceStack/wiki/CSharp-Add-ServiceStack-Reference#xamarin-studio-for-linux) - -#### [Xcode integration with ServiceStackXC Plugin](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference) - -Providing [Swift Native Types](https://github.com/ServiceStack/ServiceStack/wiki/Swift-Add-ServiceStack-Reference) support for developing native iOS and OSX Applications with Xcode on OSX. - -#### [Android Studio integration with ServiceStackIDEA](https://github.com/ServiceStack/ServiceStack/wiki/Java-Add-ServiceStack-Reference) - -Providing Java Native Types support for developing pure cross-platform Java Clients or mobile Apps on the Android platform using Android Studio on both Windows and OSX. - -## [ServiceStack IDEA Android Studio Plugin](https://plugins.jetbrains.com/plugin/7749?pr=androidstudio) - -Like the existing IDE integrations before it, the ServiceStack IDEA plugin provides Add ServiceStack Reference functionality to [Android Studio - the official Android IDE](https://developer.android.com/sdk/index.html). - -### Download and Install Plugin - -The [ServiceStack AndroidStudio Plugin](https://plugins.jetbrains.com/plugin/7749?pr=androidstudio) can be downloaded from the JetBrains plugins website at: - -### [ServiceStackIDEA.zip](https://plugins.jetbrains.com/plugin/download?pr=androidstudio&updateId=19465) - -After downloading the plugin above, install it in Android Studio by: - -1. Click on `File -> Settings` in the Main Menu to open the **Settings Dialog** -2. Select **Plugins** settings screen -3. Click on **Install plugin from disk...** to open the **File Picker Dialog** -4. Browse and select the downloaded **ServiceStackIDEA.zip** -5. Click **OK** then Restart Android Studio - -[![](https://github.com/ServiceStack/Assets/raw/34925d1b1b1b1856c451b0373139c939801d96ec/img/servicestackidea/android-plugin-install.gif)](https://plugins.jetbrains.com/plugin/7749?pr=androidstudio) - -### Java Add ServiceStack Reference - -If you've previously used [Add ServiceStack Reference](https://github.com/ServiceStack/ServiceStack/wiki/Add-ServiceStack-Reference) in any of the supported IDE's before, you'll be instantly familiar with Add ServiceStack Reference in Android Studio. The only additional field is **Package**, required in order to comply with Java's class definition rules. - -To add a ServiceStack Reference, right-click (or press `Ctrl+Alt+Shift+R`) on the **Package folder** in your Java sources where you want to add the POJO DTO's. This will bring up the **New >** Items Context Menu where you can click on the **ServiceStack Reference...** Menu Item to open the **Add ServiceStack Reference** Dialog: - -![Add ServiceStack Reference Java Context Menu](https://github.com/ServiceStack/Assets/raw/master/img/servicestackidea/android-context-menu.png) - -The **Add ServiceStack Reference** Dialog will be partially populated with the selected **Package** from where the Dialog was launched from and the **File Name** defaulting to `dto.java` where the Plain Old Java Object (POJO) DTO's will be added to. All that's missing is the url of the remote ServiceStack instance you wish to generate the DTO's for, e.g: `http://techstacks.io`: - -![](https://raw.githubusercontent.com/ServiceStack/Assets/master/img/servicestackidea/android-dialog.png) - -Clicking **OK** will add the `dto.java` file to your project and modifies the current Project's **build.gradle** file dependencies list with the new **net.servicestack:android** dependency containing the Java JSON ServiceClients which is used together with the remote Servers DTO's to enable its typed Web Services API: - -![](https://github.com/ServiceStack/Assets/raw/master/img/servicestackidea/android-dialog-example.gif) - -> As the Module's **build.gradle** file was modified you'll need to click on the **Sync Now** link in the top yellow banner to sync the **build.gradle** changes which will install or remove any modified dependencies. - -### Java Update ServiceStack Reference - -Like other Native Type languages, the generated DTO's can be further customized by modifying any of the options available in the header comments: - -``` -/* Options: -Date: 2015-04-17 15:16:08 -Version: 1 -BaseUrl: http://techstacks.io - -Package: org.layoric.myapplication -GlobalNamespace: techstackdtos -//AddPropertyAccessors: True -//SettersReturnThis: True -//AddServiceStackTypes: True -//AddResponseStatus: False -//AddImplicitVersion: -//IncludeTypes: -//ExcludeTypes: -//DefaultImports: java.math.*,java.util.*,net.servicestack.client.*,com.google.gson.annotations.* -*/ -... -``` - -For example the package name can be changed by uncommenting the **Package:** option with the new package name, then either right-click on the file to bring up the file context menu or use Android Studio's **Alt+Enter** keyboard shortcut then click on **Update ServiceStack Reference** to update the DTO's with any modified options: - -![](https://github.com/ServiceStack/Assets/raw/master/img/servicestackidea/android-update-example.gif) - -### Java JsonServiceClient API -The goal of Native Types is to provide a productive end-to-end typed API to fascilitate consuming remote services with minimal effort, friction and cognitive overhead. One way we achieve this is by promoting a consistent, forwards and backwards-compatible message-based API that's works conceptually similar on every platform where each language consumes remote services by sending **Typed DTO's** using a reusable **Generic Service Client** and a consistent client library API. - -To maximize knowledge sharing between different platforms, the Java ServiceClient API is modelled after the [.NET Service Clients API](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) as closely as allowed within Java's language and idiomatic-style constraints. - -Thanks to C#/.NET being heavily inspired by Java, the resulting Java `JsonServiceClient` ends up bearing a close resemblance with .NET's Service Clients. The primary differences being due to language limitations like Java's generic type erasure and lack of language features like property initializers making Java slightly more verbose to work with, however as **Add ServiceStack Reference** is able to take advantage of code-gen we're able to mitigate most of these limitations to retain a familiar developer UX. - -The [ServiceClient.java](https://github.com/ServiceStack/ServiceStack.Java/blob/master/src/AndroidClient/client/src/main/java/net/servicestack/client/ServiceClient.java) interface provides a good overview on the API available on the concrete [JsonServiceClient](https://github.com/ServiceStack/ServiceStack.Java/blob/master/src/AndroidClient/client/src/main/java/net/servicestack/client/JsonServiceClient.java) class: - -```java -public interface ServiceClient { - public TResponse get(IReturn request); - public TResponse get(IReturn request, Map queryParams); - public TResponse get(String path, Class responseType); - public TResponse get(String path, Type responseType); - public HttpURLConnection get(String path); - - public TResponse post(IReturn request); - public TResponse post(String path, Object request, Class responseCls); - public TResponse post(String path, Object request, Type responseType); - public TResponse post(String path, byte[] requestBody, String contentType, Class responseCls); - public TResponse post(String path, byte[] requestBody, String contentType, Type responseType); - public HttpURLConnection post(String path, byte[] requestBody, String contentType); - - public TResponse put(IReturn request); - public TResponse put(String path, Object request, Class responseType); - public TResponse put(String path, Object request, Type responseType); - public TResponse put(String path, byte[] requestBody, String contentType, Class responseType); - public TResponse put(String path, byte[] requestBody, String contentType, Type responseType); - public HttpURLConnection put(String path, byte[] requestBody, String contentType); - - public TResponse delete(IReturn request); - public TResponse delete(IReturn request, Map queryParams); - public TResponse delete(String path, Class responseType); - public TResponse delete(String path, Type responseType); - public HttpURLConnection delete(String path); -} -``` - -The primary concession is due to Java's generic type erasure which forces the addition overloads that include a `Class` parameter for specifying the response type to deserialize into as well as a `Type` parameter overload which does the same for generic types. These overloads aren't required for API's that accept a Request DTO annotated with `IReturn` interface marker as we're able to encode the Response Type in code-generated Request DTO classes. - -### Java JsonServiceClient Usage -To get started you'll just need an instance of `JsonServiceClient` initialized with the **BaseUrl** of the remote ServiceStack instance you want to access, e.g: - -```java -JsonServiceClient client = new JsonServiceClient("http://techstacks.io"); -``` - -> The JsonServiceClient is made available after the [net.servicestack:android](https://bintray.com/servicestack/maven/ServiceStack.Android/view) package is automatically added to your **build.gradle** when adding a ServiceStack reference. - -Typical usage of the Service Client is the same in .NET where you just need to send a populated Request DTO and the Service Client will return a populated Response DTO, e.g: - -```java -AppOverviewResponse r = client.get(new AppOverview()); - -ArrayList