What's New? - update history

For updates before Oct 1, 2015 see here: Archive

Version, May 14, 2016

No new big features, just bug fixes and patches.
  1. New flag DbOptions.ForceArraysAsLiterals - you set DbOptions when you create DbSettings object, preparing to connect you entity app to the database. This flag suppresses use of array parameters in db server (Postgres, MS SQL). For MS SQL array parameters are sent using a custom user table type (in database), which VITA creates automatically. In some scenarios this is not possible, or not desired. So in this case you can set this flag, and LINQ expressions like 'list.Contains(value)' will be translated into SQL by directly injecting the list of literals: 'WHERE t1.Id IN (1, 5, ... 22)'. The other effect is that VITA does not create stored procedures that use this operation - it uses plain SQL instead.
  2. Grant EXECUTE permission on dbo.VitaArrayAsTable_ type in MS SQL Server - it turned out this permission is needed when connecting to database with a low-privilege login.
  3. Identity column initialization on NewEntity - identity columns are initialized in new entities to negative values from auto-decremented counter. They are set to real values generated in the database when the entity is saved. Previously these columns were zeros until saved - this caused some unexpected wrong results in entity comparisons (entities are compared for equal by comparing PK values).
  4. DateTime parameters in URLs - it turns out the default behavior in Web API for datetime parameters is the following: the value is read as UTC, but then converted to server local time. This is quite annoying, and I did not find any way Web API setting to fix it. It is quite in contrast with datetime treatment by JSon deserializer (Newtonsoft) that interprets all date strings as UTC (with default setting). The fix is in SlimApi (in VITA) - the URL-bound parameters are checked for datetime/Local - and converted back to UTC automatically.
  5. Async methods in SlimApi controllers are supported - this is not a fix, but a confirmation that these methods do work as expected. Added a unit test calling an async method in SpecialMethodsController.

Version, April 10, 2016

  • Include functionality - finally, it is here. You can now add one or more Include clauses to a query, to specify which related entities to include:
var qOrders = session.EntitySet<IBookOrder>().Where( . . .)
  .Include(o => new { o.Lines, o.User }) 
  .Include((IBookOrderLine l) => l.Book) 
  .Include((IBook b) => new { b.Publisher, b.Authors});  
You can include more than one Include clause; you can specify a single 'target' property, or multiples with auto object ( new {...} ); you can target a single property ref (o.User), one-to-many list property (o.Lines), or many-to-many lists (b.Authors).
Notice the two forms of Include methods. The first include in the example uses an implicit input type (IBookOrder) from the query result; two others use explicit typing of the argument.
Unlike implementation in EF, VITA does NOT use extra JOINs in the main query; instead, it runs an extra query for each Include expression. Which way is more efficient is debatable, either is more efficient in various cases. But with VITA's approach we are not limited in number of extra clauses, it does not result in overly complex combined query. Notice that include specs are 'cross-referencing' and recursive. The first include (o.Lines) results in a query that returns related IBookOrderLine rows (just single query for all orders, not one per each order). Then the second Include (for IBookOrderLine) kicks in and causes loading all referenced books (single query, for all order lines in all orders). Finally, the last Include for IBook entity kicks in and results in a single query to retrieve publishers, and another query for all authors. Note that the order of Include() calls in the c# code does not matter. There is a protection against circular references and infinite loops (ex: include of employee.Manager, resulting in another employee record). To avoid infinite loops, the include queries run max 2 times for a given entity type. Another optimization - before running the query, the list of IDs is cleared from duplicates.
You can specify Include clauses directly in the query, or add them to the OperationContext instance - in the latter case the includes will be applied to any query executed with the context.
See TestLinqInclude unit test for examples of different types of queries. The tests actually check that once we load the entities with includes, no extra db queries are executed when we step through internals of the entities.
The Include queries internally are DB queries that select target rows by array of key values (primary or foreign key). So they use array/list type of parameters - the feature just implemented in VITA.
  • Array/list DB command parameters - array-type parameters are not supported by all servers. The only server supporting it directly is Postgres. For MS SQL Server, you can pass an array of values using table-type parameter (DataTable on ADO.NET side). For these 2 servers the select-by-array SQLs are implemented as stored procedures. Other databases (MySql, Sql CE, SQLite) do not support list-type parameter values. For these servers, the SQL Query is build by directly injecting the list of literals into the SQL (ex: "... WHERE book_id in (1, 5, 7)"). So for MySql, even if you use stored procedures, the 'array-type' queries are not converted to procs and remain as plain SQL templates, formatted on-the-fly just before execution.
  • Internal cleanup, fixes, refactorings for performance - some internal fixes, you might notice improved performance in some cases. Also fixed file log issue - SQLs were appearing twice in the file; was introduced when LoggingApp was separated from 'main app', now fixed. Fixed a bug with web session expiration, now should expire for sure after inactivity for 20 minutes.

Version, March 19, 2016

  1. Locking implementation for all servers - (all except SqlCe and SQLite). Completed implementation for SQL Server, MySql and Postgres. Created real unit test (20 threads hitting on 5 docs). Worked perfectly for MySQl and Postgres, but initial implementation for MS SQL failed, miserably with deadlocks. After much research, googling and discussing in TSQL forum, finally figured it out. Implementation for MS SQL requires to have SNAPSHOT_ISOLATION set to ON for the database (it is OFF by default). To automatically set it, you can use the same migration script I use in BookStore sample app. So the tests using the sample should work OK on your machine, with new or old VitaBooks database. I will update the Locking and Concurrency document. I also plan to write an article on codeproject to share my experiences in locking.
  2. session.GetDbConnector() with admin option - now you can optionally request connector with 'admin' connection string, to perform high-privileged actions. DbSettings object has 2 connection strings: admin-level connection for schema updates, and regular connection for normal app read-writes. This admin-level connection is used in migration script that enables snapshot isolation level mentioned in previous item about locks.
  3. Sequences support - added support for DB sequence objects for MS SQL and Postgres; see TestSequences unit test. New module.RegisterSequence method, Sequence attribute.
  4. TaskHelper class - sync/async bridge - figured out simple and reliable way to run async methods synchronously. See TaskHelper.RunSync() method. This is quite a hot topic out there, we are forced into a mixed sync/async world by MS, but bridge? The problem is thread deadlocks, the code might work in unit test (console app), but deadlocks under ASP.NET. Here is my solution, might be not very efficient, but works well under ASP.NET. INotificationService.Send - sync method is added, to simplify sending notifications, internally just uses RunSync wrapper. Notice no-wrap-exceptions facility in TaskHelper, to rethrow certain exceptions without wrapping.
  5. EventLog module in LoggingApp - new logging facility for logging free-form events on the client and/or server. A typical use - for analytics. You can track events like "Banner-click", or times spent on certain pages. Client UI/JavaScript code can directly submit events to the server. See TestEventLog unit test in WebTests project for a demo.
  6. IpAddress, UserAgent, clientOS, TimeZoneOffset added to UserSession - now saved in user session table, to make things easier. All but timezone offset is captured automatically. For setting timezone offset there is a separate API call, see TestSessionInfoApi test. You should make this call right after login. The offset can be used when you need to calculate date-time in user timezone (ex: send email with some temp access code, and note that is expires on ...).
  7. Bug fix for multi-tenant apps - in setups with multiple data sources (one entity app connected to multiple databases) only the first connected database gets its schema updated. Now should be fixed.
  8. Bug fix: identity handling in MySql without stored procs - previously identity worked correctly in MySql only if you used stored procedures. Now fixed, works with plain SQLs and stored procedures.

Version, March 2, 2016

  1. Multi-tennant apps - allow DbModel to be shared between databases connected to the same entity app. To share DbModels, use single instance of DbModelConfig to create DbSettings object for each database being connected. Make sure Options flag set has ShareDbModel flag.
  2. Mapping area to schema(s) By default, the name of entity area is the name of the schema (like dbo) in the database. However, you can map it to a different schema when connecting to the database. Just use dbSettings.ModelConfig.MapSchema(areaName, schemaName) method to map to custom schema. This comes handy when connecting to multiple MySql databases residing on the same server. MySql treats schema and database as the same things, so different databases are in fact simply different schema in the same database. To associate a data source (Database in VITA) with different schemas, use this mapping. Note that EntityArea no longer has Name and Schema properties, just name - so the old constructor is obsolete, use new one with just one parameter.
  3. Locking bug fix - minor bug fix in locking extensions. Locking Guide document is coming soon
  4. Bug fix: large batch update with Identities - fixed bug causing failures in large batches with identity-based PKs. Added unit test.
  5. Connection lifetime management refactoring - now better with Lifetime property of DataConnection. Now the system correctly resolves the 'to close or not' question when releasing connection (ex: locks).
  6. Stored proc permission grant refactoring - minor refactoring, the code moved to MS SQL driver where it belongs actually. Role names are now in DbSettings class. Also added explicit SELECT grants for views.

Version, Feb 25 2016

  • Data Filter for list properties - You can now have a filtered list properties, like publisher.FictionBooks. Currently implemented only for one-to-many lists, many-to-many will come later. You specify filter in OneToMany attribute's Filter:
  // IPublisher entity
  [OneToMany(Filter=" {Category} = 1")] //fiction
  IList<IBook> FictionBooks { get; }

See IPublisher entity in BookStore app and TestListProperties unit test for usage example
  • DataAccess service - now thread-safe and based on dictionary, so it's ready for hundreds of attached databases in multi-tenant environment.
  • Bug fix - Web session expiration - added unit test.
  • NotificationListener helper class - added Filter and made thread-safe

Version, Feb 22 2016

  1. Data Migrations - note that these are not schema migrations like in EF. In VITA, db model is updated automatically from entity model. What you can add is some data manipulations linked to certain version upgrades. Breaking change: instead of "DbModelUpdate" the framework now uses DbUpgrade (like DbUpgrageMode enum) - because upgrades are now not only model/schema changes, but also custom data operations (migrations). Migrations are defined at entity module level, and are linked to particular module version. To define migrations, override EntityModule.RegisterMigrations method. You can define 2 types of data updates: plain SQLs to run, or normal VITA-style operations using entity session. For SQL migrations you can specified timing, when to run these - before, after, or in the middle of model/schema update operations. EntitySession-based commands are run after model update is completed. See TestSchemaUpdate unit test in Basic tests project for an example. Also look at Login module's LoginModuleMigrations.cs_ code for a real-life example - this code renames old templates to new naming pattern. Note that from now on, properly versioning your modules becomes important, so always provide explicit version parameter in module constructor. See modules defined in Vita.Modules assembly for a suggested code pattern. I plan to publish a doc on migrations soon.
  2. Record locking - prototype for now, MS SQL only. See TestLock unit test method for simple demo. I am planning a separate documentation page for this feature as it goes along. For now, brief how it works. Entity session's GetEntity and EntitySet<T>() get 'overload' version (as extension methods) that take an extra LockOptions parameter. There are 2 locks availabe - SharedRead and ForUpdate. In both cases, the system starts a transaction and executes the SELECT statement with corresponding lock hint. The result is record lock hold until transaction is committed - thru SaveChanges or session.ReleaseLock methods. Suggested pattern: use read lock on document header (BookOrder) to load BookOrder header record and all related records (order line). To update order (header or details) - put an update lock on header record at the beginning. The locks ensure that reads are consistent (document is not updated by other thread while you read its parts), and that no two updates collide. I plan to publish a brief document on locking soon.
  3. New NotificationService - generalization for IEmailSendService; sends templated messages thru registered providers. One implementation is EmailNotificationProvider - combination of templates stored in db (template module) and Smtp services. Other possibility - external email provider with template system (Mandrill). Login module sends templated messages (like sending Pin). With Notification service the template name pattern changed: now it is notificaiton-type + '.Email.Body' (or '.Email.Subject'). The renaming of existing templates happens automatically, using data migration action in login module. Note that NotificationService's main method SendAsync is async - beware, very easy to get into thread deadlock when trying to run synchoniously. More on this in section below.
  4. DbInfo module changes - the module is refactored, stores per-module version information. It also keeps the hashes of the DB views. I had a lot of trouble in the past with maintaining DbViews for MySql and Postgres. The problem is detecting on upgrade if the view definition has changed and needs to be upgraded. Both servers do not store original source code of the view, so it was quite a problem. Now I introduce 2 improvements. First, the hash of source code of the view is saved in comment line in the view body (this trick is used for stored procedures too). Some servers reformat the view but preserve comments, so the hash can be retrieved from comment in existing view, and used to detect if the view changes. Postgres does not keep comments, so for this case (if hash comment line is not found), the hashes of all views are saved in blob field in DbInfo table. On new version upgrade the hashes are retrieved and compared with new hashes, and system detects if view actually changed.
  5. WebApiClient is now multi-threaded - and all-way async. Sync methods (same as before, like ExecuteGet<>) are now extensions, in 'Sync' namespace, so you have to add using Vita.Modules.WebClient.Sync;. Just to make it an explicit choice - going Sync over async methods; be aware - really easy to get into thread deadlock when running under ASP.NET.
  6. Async/await methods - I have started switching some methods to async/await pattern. Looks like this pattern is enforced on us, I personally don't like it so far, very unhappy with the way the whole things works - so invasive and fragile. Once you hit some async method, you are almost forced to go async all the way up; and very easy to hit thread deadlock. The worst thing is that everything might be working OK in unit test, in self-hosting scenario, but in real Web app under IIS the code suddenly locks. (Redmond - fix the selfhosting scenario then, so it runs under ASP.NET sync context!) Hit it myself several times. But it looks like it's inevitable, the only way to provide high throughput under ASP.NET is to go async. I plan to introduce support for async methods in SlimApi controllers soon, so we can go async from top down. Warning - be careful when calling async method from regular, sync method, like NotificationService.SendAsync. To be safe, run it by unloading to another thread (example in LoginModule.SendPin method):
        Task.Run(() => _notificationService.SendAsync(context, msg)); //unload to another thread

Version, Dec 30 2015

  1. Warning - known issue for Postgres. Views have to be recreated if a column in the underlying table changes. Attempt to modify a column definition (Nullable flag) will cause error in Postgres if there's a view using this column (MySql and MsSQL do not complain). In the future the update schema process should detect the case and drop/create the view.
  2. WebApiClient - renamed and refactored HttpClientWrapper. The class used for implementing RESTful clients is substantially refactored, renamed into WebApiClient class, and moved from Vita.Web to Vita.Modules assembly. The main change is cutting dependency on Web API packages, so that the client can now be used in non-Web apps (desktop, console, or class libraries) without the need to reference quite large Web API infrastructure. The only dependency needed now is Json Serializer (Newtonsoft or you can use custom serializer). The earlier version used Web API TypeFormatters for serailziation/deserialization, and this was overlook that in fact what was need is just a serializer.
  3. BookStore Web Application sample - this is huge. I've been lacking time (and skills) to implement a complete UI application demonstrating all VITA features. Luckily, Dave Clemmer (moplus) came to rescue and built this application. Now you can see in action all the features that the framework provides for building entire server-side stack - Slim API controllers, Web API integration, logging and diagnostics, etc. Enjoy it! We plan to add more features in the future, like demo of all login facilities.
  4. Login module - GoogleCaptcha refactored, added GoogleAuthenticator. Google Authenticator might be used now as an extra factor in multi-factor login, or in password reset process.
  5. Sample data generator is now in a separate assembly. The assembly also contains a facility for importing book records from Google Books API. This import class actually demonstrates how to build strongly-typed clients based on newly refactored WebApiClient class.

Version - Nov 27, 2015

Summary: several bug fixes for some obscure cases in Login module; internal enhancements in several areas; GrantAccess attribute for 'authorization granted by ref', search improvement (avoiding total query); API controllers in BookStore sample app and some refactoring of BookStore sample; support for returning images (binary streams) in API controllers.
  1. Login module fixes and enhancements - there were a few situations when login got disabled (locked out) after incorrectly handling end of expriration/suspension periods - were discovered hard way after deploying to production of our app, a few embarrassing moments. Now hopefully all is fixed - let me know if you run into anything. Enhancements - SearchLogins method now returns SearchResults<ILogin> object, which includes total count - just like other search APIs. Login module now tracks LastLoggedIn datetime value and returns it in LoginResponse object after successful login. Also added some useful methods in API, like enabling/disabling login in administration API.
  2. LoginFailedTrigger is now created automatically by Login module, from parameters in LoginModuleSettings. Previously you had to create it in EntityApp constructor. If you had it there in your app - remove it. If you do not want trigger to be created, set to null the property for trigger's settings in LoginModuleSettings.
  3. Authorization - GrantAccess attribute on entity-type reference properties. The GrantAccess attribute placed on a property of entity type (ex: review.User) instructs the authorization subsystem to grant access (read or write) to all or some properties of the target object, even if current user is not granted access to target entity. A typical case in BookStore sample. In general, the authorization rules should prohibit non-employee users to access other users' records - except their own. So the access to IUser entity is granted only to the user itself. However, there is a case of book reviews: users post reviews which are available to read by anybody. The review listing should also show the reviewers; identity, user's DisplayName. The only way to make it possible previously was to configure DisplayName as a separate resource and grant Read access to this resource to any user. That's the way if was setup in BookStore sample. This resulted in too loose permissions - any user (even anonymous visitor) was granted access to DisplayName property of any user. With GrantAccess attibute we can now solve the problem in a simpler and more straightforward manner. We put GrantAccess("DisplayName") on IBookReview.User property, and system interprets this as: whenever the current user has access to IBookReview entity, grant him access to DisplayName property of the target IUser entity. No need to create special resource consisting of just one column. See BooksStore app (IBookReview entity) for a sample implementation.
  4. ExecuteSearch enhancements: session.ExecuteSearch helper method is used for executing search LINQ expression and returning results (page) with total count. The old method ran 2 queries, total query first, and then actual query with filter and paging. However, in some situations we do not need to run total query - if the actual query returns less than page-size number of rows. It means that we see the last row in a result set, so total is skip-value+returned-rows-count. New implementation now runs actual query first, with 'take' parameter value of page-size plus 1 - we request one more row than we actually need. If the return row count is page-size plus 1, then we have to run total query. But if the count is less than requested max, then we can deduce total count by adding 'skip' and # of returned rows. The situation when it is useful is more common that might seem at first - it is not just at the last page of multi-page results listing. In many cases search function is used not to search but to lookup a row by known and mostly unique property which is not primary key - like book by title or person by last name. In this case the lookup call returns 1 row in most cases (maybe 2, or a few but less than page size) - so one query would be enough and total query is not needed in all these lookup cases.
  5. BookStore sample extended - (almost) complete set of API controllers - all except administration, covering browsing, user signup and ordering. Getting ready for AngularJS-based app with RESTful controllers at the server. A controller for administration functions (creating books, authors, internal users) to come soon.
  6. Returning images in RESTful API (and binary streams in general). Books sample is extended, now books might have cover image. Image is stored in a separate table and is referenced by a key in Book table. Image ID is added to Book model object returned by Catalog controller. This ID can be injected into a URL of image tag in UI - the target endpoint is served by controller's method that returns a binary stream with property content type header, so it will be displayed on the page. Images table is configured to be cached (sparse, single-records cache), so repeated calls are served from cache in memory. See Catalog controller in sample app for more details.
  7. Authorization container for roles and activities - some changes in suggested approach to creating and keeping authorization objects. Now I recommend to make it a non-static class and create/save it as a property of a module. The authorization objects (resources, permissions, activities, roles) belong at entity module level, so should be defined and instantiated with the module. See BookStore sample project and BooksModule for an example and recommended practice guide.
  8. Diagnostics controller - in BookStore project. Implements special functions that are very useful in practice of development and testing: heartbeat check method; throw error on demand - to test error handling; get/set time offset for testing time-dependent functions. See more detailed info in controller's source code.
  9. UrlTemplate column in WebCallLog table. In addition to Request URL, UrlTemplate stores original route template for a controller method. Actual URL might include parameters, ex: URL 'api/books/123' with template 'api/books/{id}'). Having template in log record makes it easier to group rows and compute stats.
  10. ApiRoute attribute might be skipped - previously any API endpoint required both ApiRoute and one of the HTTP method attributes (ApiGet, ApiPost etc.) - even if ApiRoute value was empty string. Now ApiRoute might be skipped - system assumes empty value of sub-route.

Version - Oct 30, 2015

  1. DbViews definition bug fix - in some cases the SQL generated for DbViews was missing aliases for output values (when value was a result of subquery), which caused error when creating the view. The bug is fixed.
  2. Batched updates, for big batches was running into upper limit for number of parameters for a Db command. (MS SQL has upper limit of 2100). Now fixed. The system breaks the batch into several commands if necessary - if number of parameters reaches 2000.
  3. Case-insensitive search - there were two problems. MS SQL, MySql, SQLite are case-insensitive by default - string comparison in WHERE clauses are case-insensitive. Usually search queries are meant to be case-insensitive, so this worked as desired. But when the search query hits the table that is fully cached, the query is rewritten to execute against in-memory lists in cache. This Linq-to-objects query was case-sensitive (as expected, c# '=' operator for strings is case sensitive), so the results would be different from the query executed in the database. Now the cache query rewrite takes into account the default case sensitivity of the database, and the result query is the same-case-mode as the database. This includes '=', and LIKE (Contains, Includes) operators. As a result, any query (against cache or database) brings the same results. The other problem is that Postgres is case sensitive by default, so queries are case sensitive. Sometimes this is what is needed, but for search queries usually the case-insensitive behavior is desired. So now for any query you can enforce case-insensitive behavior using 'WithOptions(QueryOptions.ForceIgnoreCase)' method. In this case for server like Postgres the query is translated into a case insensitive version (for Postgres the 'a=b' is translated into 'a ILIKE b'). The search helper methods in VITA (ExecuteSearch) set this option automatically.
  4. MS SQL schema update: add WITH NOCHECK to ADD COLUMN statements - for columns that are nullable foreign keys. Without this NOCHECK option the column add was failing if the table was not empty, for some strange logic on the server that was expecting the non-null valid references in this new column in existing rows. Now column can be added successfully with NULL value in all rows.
  5. MS SQL: explicit GRANT EXECUTE for all CRUD stored procedures. It is usually a good idea to use a non-dbowner SQL Server account for data access by the application. It better be an account with limited rights, so it cannot alter database schema. It turns out this non-dbowner account should be explicitly granted permission to run stored procedures, each proc individually. Now schema update process adds a 'GRANT EXECUTE TO public' for each CRUD stored procedure. The 'public' is one of pre-existing server roles, but you can change it to whatever role you want in VITA setup. Now a weakened account for data access can have 3 roles: dbdatareader, dbdatawriter and public - which will enable it to call CRUD stored procs and execute LINQ statements.
  6. Bug fix - Web call logging. The request body was not logged (left blank) in Web call log when hosted under IIS (it was OK for self-hosted dev/test server). Now it's fixed.
  7. Refactoring of Operation log - now log entries are grouped by Web call, and put as multi-line text into a single record.
  8. BackgroundSaveService now logs stats of each bulk save operations in operation log, ex: Background save completed, records: 42, save time: 7 ms, total time: 9 ms.

Version - Oct 13, 2015

  1. Persistent session module is renamed to UserSessionModule and is included into the LogginApp. So if you use session module in the main app and use LoggingApp, then remove the session from the main app. The IUserSessionService will be still available in the main app. User session module no longer has the 'LastUsed' table that was storing date-time the session was used. Now the column is in the main table, and it is updated using update LINQ command (scheduled for execution - new feature, see below).
  2. Scheduled execution for LINQ non-query commands. A new extension method session.ScheduleNonQuery(query, ...) let's you schedule the query to execute not immediately but when session.SaveChanges is called - either before or after the updates are applied, but within the context of the transaction.
  3. Getting total count for a search LINQ query. A new extension method session.ExecuteSearch executes a search query, and additonally gets total count of results by executing the query without skip/take arguments and getting the count of the results. The method returns an instance of SearchResults<T> which contains a TotalCount of rows and the list of result objects. The result object type (T) might be different from base entity if you provide an optional converter function (ent=>ent.ToDto()). See sample method SearchBooks in the BookSearchHelper.cs file for an example of usage.
  4. Logging entities in the LoggingApp had been refactored a bit, now have the same set of common columns (Id, UserName, UserSessionId, WebCallId); UserName holds a duplicate information - if we have UserSessionId we can get all user information from UserSession table; but if there's no session, UserName can be used. Additionally having user name in the table simplifies querying and analyzing information in SQL-based tools.
  5. DbInfo module - added version information for each module. DbInfo module has new table DbModuleInfo which holds version information for each entity module in the entity application. And EntityModule class now has a Version property. Since entity modules are isolated units of functionality evolving independently, it makes sense to track current versions for each module. In the future we might add special handling events at module level, to add specific actions (SQL commands) when module in the application is being updated to newer version - system can now detect this.
  6. Vita.Entities.Web namespace. Web-related classes in the core VITA assembly (WebCallContext, Slim API attributes) are moved to namespace Vita.Entities.Web_ - seems more logical and cleaner.
  7. Handling of Authentication, X-Versions tokens These tokens (cookie or web headers) are now handled automatically by WebCallContextHandler itself (all handling moved away from session module), and you specify details of these tokens in WebCallContextHandlerSettings. UserSessionModule now simply uses values in the WebCallContext (in the previous version the Authentication token was 'described' in the user session module settings).
  8. OperationContext.Values dictionary is now separate from values in UserSession - previously it was the same shared object. Now you choose to put the value into one or the other. If you want the value to be preserved between Web calls, put it into UserSession.Values. Note that if you put it in user session, it will still be visible to methods that call operationContext.GetValue(name) - if value is not found in operationContext.Values, it is looked up in operationContext.UserSession.Values, so for things like authorization filters the location of the value does not matter.
  9. Login module refactorings - very minor
    1. Password change method now requires old password, for extra security
    2. Email verification with a pin - in situations when several pins were generated (user clicked the button several times) - any valid pin would work to verify email.
    3. Login process now has failure count (default 5), and will cancel the process after user failed certain number of times. Example: password reset process, user fails to answer secret questions 5 times in a row.

Version - Sept 22, 2015

Critical bug fix - SecureSession.CanDelete was failing with exception

Archive: updates before Oct 1, 2015

Last edited May 15, 2016 at 4:50 AM by rivantsov, version 73


No comments yet.