Configuring NHibernate second level caching in an MVC app - asp.net-mvc

I have an MVC3 app that's using NHibernate. All was going well until I started to try and add second level caching. After browsing the web for a few hours I finally found what I think is the right dll (NHibernate.Caches.SysCache2.dll) and have added it to my project.
However, I can't find any help for configuring it with an MVC app. All the examples refer to having an App.config file (I presume this is for Web Forms). I'm a Java developer who's learning .Net so I'm not so familiar with how to rig everything up.
Could someone point me in the right direction. I'm using xml hibernate (hbm) files.
Thanks.

I'm using 2nd level caching with MVC3 and NHibernate.Caches.SysCache.dll like this...
1st, add a config section to your web.config file like this
<configSections>
<section name="syscache" type="NHibernate.Caches.SysCache.SysCacheSectionHandler, NHibernate.Caches.SysCache, Version=3.0.0.4000, Culture=neutral, PublicKeyToken=6876f2ea66c9f443"/>
</configSections>
add a syscache section to your web.config under your configuration section like this:
<syscache>
<cache region="SomeCustomNameRegion" expiration="86400" priority="5" />
</syscache>
in my hibernate.cfg.xml file i have the following properties added:
<property name="cache.provider_class">NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache</property>
<property name="cache.use_query_cache">true</property>
<property name="cache.use_second_level_cache">true</property>
I'm using FluentNhibernate to create my mappings and add this to support caching:
public CustomerClassMap()
{
Cache.NonStrictReadWrite();
Id(x => x.Id);
Map(x => x.Name);
//... more properties
}
And then in my data access code, I have something similar to this for queries that I want cached:
public IEnumerable<Customer> GetAllCached()
{
return Session.CreateCriteria(typeof(Customer))
.SetCacheable(true)
.SetCacheRegion("SomeCustomNameRegion")
.SetCacheMode(CacheMode.Normal)
.AddOrder(Order.Desc("CreateDate"))
.List<Customer>();
}
Here are some helpful links to get into a little more detail. There's nothing specific about MVC3 that you need to worry about, and most is unchanged from earlier versions of NHibernate as far as i can tell.
http://www.klopfenstein.net/lorenz.aspx/using-syscache-as-secondary-cache-in-nhibernate
http://blog.symbiotic-development.com/2008/02/27/more-configuring-nhibernate-caches/

Related

Using Strongly Typed models in Umbraco 7.6.9?

I have tried looking into using Strongly Typed models (setting Umbraco.ModelsBuilder.ModelsMode to either AppData or Dll) for a while now, and I never fully understood how it works.
I already changed the Umbraco.ModelsBuilder.ModelsMode value and I generated the models inside the backoffice ModelsBuilder, then I included the App_Data\Models into Visual Studio, but what then?
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ContentModels.Home>
#using Our.Umbraco.Vorto.Models;
#using Our.Umbraco.Vorto.Extensions;
#using ContentModels = Umbraco.Web.PublishedContentModels;
This is the code for my Home view. No matter what I try, I cannot access the #Model.PROPERTY or #CurrentPage.PROPERTY from my content. I can see the different properties inside my MODEL.generated.cs files.
What steps do I need to take, in order to do things like #Model.PROPERTY?
Okay, so it seems like there has been some changes in the newest 7.6.9 release (or maybe 7.6.8). This is what I had to do now:
<add key="Umbraco.ModelsBuilder.Enable" value="true" />
<add key="Umbraco.ModelsBuilder.ModelsMode" value="Dll" />
Then I can go into the backoffice and generate the models. The models are included into the project (location: ~\App_Data\Models\). Umbraco.Web.PublishedContentModels.dll from the ~\bin\ folder has to be included as well.
Then, because of .NET Core I think, I got an error when I tried loading my application saying this:
More than one type want to be a modle for content type File
This was caused because I had included everything inside ~\bin\, which means I had also included my Project.dll, Project.dll.config, and Project.pdb files. The Project.dll file also includes the same models, apparently, so I had to exclude those 3 files.
Now it simply works and I can now do #Model.Content.PROPERTY flawlessly.
You're not talking about "Dynamic" models, but Strongly Typed Models generated by Models Builder. By default Umbraco ships with PureLive setting which is keeping models in memory and generates them on the fly. It can be considered as "dynamic".
The tool and it's behaviour is well documented here: https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki
Regarding modes of it, you can find all about it exactly in this place: https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Builder-Modes
But answering your question - after you've changed the configuration, you need to compile your application as you need to keep those classes inside the DLL with which you're shipping your website. You're also able to regenerate models straight from your Developer's dashboard in Umbraco Backoffice.
You need to remember that if you would like to use DLL, LiveDLL or PureLive configuration - you need to get rid of classes generated inside your AppData or any other directory used with this mode as you'll experience errors saying about 'More that one type want to be a model for content type File'.
After that you should be able to access all properties of the document type via Model.Content.PropertyAlias. You probably missed the Content object, which is the strongly typed, IPublishedContent representation of you document.
Hope it will help you to make it work :)

Access to Resources resx file failing. (MVC & ErrorMessageResourceType)

Been troubling me for hours this! As a newbie to MVC, have followed various ways of trying to access a resource file in the App_GlobalRecources folder.
The RESX file properties are Embedded Resource as build action, and custom tool is set to PublicResXFileCodeGenerator.
I also have this in the web.config (system.web):
<globalization enableClientBasedCulture="true" culture="auto" uiCulture="auto" />
In a view model, (although have tried accessing from functions with the same problem), I have the following:
Public Class ExternalLoginConfirmationViewModel
<Required(ErrorMessageResourceType:=TypeOf (Resource1), ErrorMessageResourceName:="Test")>
<Display(Name:="Email")>
Public Property Email As String
End Class
The problem is that I get the following error:
'Resource1' is a class type and cannot be used as an expression.
I cannot figure out why as have tried numerous suggestions from numerous websites, and get the same error.
OK - so seemed to have solved it.
Every website I have found advises the VB below (or the C# equivalent):
<Required(ErrorMessageResourceType:=TypeOf (Resource1), ErrorMessageResourceName:="Test")>
Not one website has suggested this which seems to have solved the problem, although I don't know why:
<Required(ErrorMessageResourceType:=GetType(Resource1), ErrorMessageResourceName:="Test")>
Anyway, hope this helps if someone else has the same issue.

Is it Possible to modify how the raw .edmx file is generated in Entity Framework 5

I am using the Entity Framework 5.0 DB-First approach, within an Asp.Net 5 MVC application, to connect to an oracle database. All works fine against the database for which I generated my EF data model, but I have 3 different (identical) environments set up _PROD, _UAT, and _DEV.
I have config transforms setup to point to the appropriate environment for which I am deploying. The problem is, once i switch connectionstrings to a different Schema ("database" for sql folks) it produces
ORA-00942: table or view does not exist
After hours of poking around, I figured out why. After looking at the raw .edmx code file, i found that the designer is applying the Schema ("database" for sql folks) name to all of the Entities within the Entity Container node, note the REV_ALLOC_DEV below.
<EntityContainer Name="ModelStoreContainer">
<EntitySet Name="LOG_EVENTS" EntityType="Self.LOG_EVENTS" Schema="REV_ALLOC_DEV" store:Type="Tables" />
<EntitySet Name="PAGE_LOCK" EntityType="Self.PAGE_LOCK" Schema="REV_ALLOC_DEV" store:Type="Tables" />
<!-- Bunch more entities... -->
</EntityContainer>
If I go in and manually modify the file, to Remove that Schema name from all of the entities within the Entity Container "and also in a few other spots where there is some raw sql select statements" then everything between the multiple databases works like a champ.
So my question is: Is there any way to modify how that raw .edmx xml is generated by the designer, perhaps through .tt file or something of the likes so i can automatically remove the Schema ("database" for sql folks) name from being appended.
Also as a note, When in the properties of the .edmx designer, I already know about the Database Schema Name property, currently that is set to dbo, which i see actually just blanks out the defaultdatabseschema property in the .edmx file. example below. Perhaps there is a way to set this per environment to read a SchemaName value from my transformed configs, but I wonder if this property is primarily more geared toward SQL schema, and not oracle schema, so i've been more inclined to try and find an answer to my above question.
<DesignerProperty Name="DefaultDatabaseSchema" Value="" />
Another note.
I've seen a lot of references to:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("MyDefaultDbSchema");
}
but I believe this is really only a code-first solution.
Have you managed to modify it? Instead of trying to modify the files, have you thought about creating an agnostic connection?
please take a look at this link from Sergey Barskiy .
On the web config file there are 3 references:
csdl - which represents the conceptual schema;
msl - to translate .net queries into database commands;
ssdl - contains information about the RDBMs
All three schemas are compiled to produce the DLL of the model.
The author creates two models (one for Oracle and the other one for SQL) and then dynamically switches from one to the other.

Accessing sitecore content with virtual folders

The Issue
We have two sites, one domain, we want to setup a virtual directory on the domain which can access the second site.
IIS virtual directory doesn't seem to do the trick, sitecore does not seem to play nicely.
Is there a potential work around using sitecore?
The Environment
We have the following folder structure for two of our sites:
C:\Sitecore\Site1
C:\Sitecore\Site2
Site 1 and Site 2 both connect to the same web, core and master databases.
To access the cms for both sites in the browser we do:
www.mysite1.com/sitecore
From Site 1's cms we create content, layouts and templates for Site 1 and Site 2.
The Solution
What we did is in the first sites web.config we defined the site as normal:
<site name="site1" hostName="mysite1.com" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/MyItem1/" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
In the second sites web.config we defined the site slightly differently:
<site name="site2" hostName="mysite1.com" virtualFolder="/Site2" physicalFolder="/" rootPath="/sitecore/content" startItem="/MyItem2/" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
The second site we defined a virtual folder which you can notice above that was the only difference along with the obvious start item differences.
Site 1 will respond like normal. You can visit mysite1.com it will load the start item relevant for website 1.
When you visist mysite1.com/Site2/ it will load the virtual folder defined in the second site and load its relevant start item.
That is pretty much it works like a charm.
And finally #Mark Ursino thanks for your help.
To Note
You need have sitecore scalability configs enabled for any of the above to work
From what I think I understand, I think you need to make some changes in the config to set the "sub-folder site" as a virtualFolder:
<site virtualFolder="/subsite" physicalFolder="/subsite" rootPath="/sitecore/content" startItem="/MyItem/" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
Note that virtualFolder="/subsite" and physicalFolder="/subsite" point to the subfolder, but I don't think you need that physical folder really there.
Reference used.
Maybe this post will be useful http://sitecoreblog.alexshyba.com/2012/02/have-sitecorecontent-in-your-link-time.html

ASP.NET MVC Tracing Issues

Question
How do I get ASP.NET MVC trace information to be consistent for in-page trace output as trace.axd? I may just be missing something obvious, please call it out if you see it.
Background Info for Traditional ASP.NET
So back in the regular ASP.NET days, you could simply add the following to your web.config:
<system.diagnostics>
<trace>
<listeners>
<add name="WebPageTraceListener" type="System.Web.WebPageTraceListener, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</listeners>
</trace>
</system.diagnostics>
...
<system.web>
<trace enabled="true" pageOutput="true" writeToDiagnosticsTrace="true"/>
...
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="1" compilerOptions="/d:TRACE" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
Then you could add the following in your pages:
HttpContext.Current.Trace.Write("Write Trace Here");
or
System.Diagnostics.Trace.Write("Write Trace Here");
And if you hit your page (i.e. localhost:61115/Default.aspx), you would get a nice trace table with your custom trace embedded with asp.net page events:
aspx.page Begin Load 0.00343 0.000357
test 0.00462176 0.001192
aspx.page End Load 0.00526904 0.000018
Hitting localhost:61115/Trace.axd?id=0 would retain the same trace results as the in-page trace outputs.
Background Info on ASP.NET MVC
Unfortunately, I cannot get this to work in ASP.NET MVC 2.0 for reasons unknown to me. I use similar web.config settings as ones listed above. What is interesting is that I can only get traces to partially work. So if I hit the functionality equivalent default page (aka index action method of my homecontroller), I see all of the traditional asp.net page events such as preinit, preload, prerender, etc but no custom trace msg using either System.Diagnostics nor HttpContext.Trace.Write.
However, if I turn to the Trace.axd?id=0 file, I'm greeted with my custom trace messages but no ASP.NET page event trace output. I must be missing something here that is causing this inconsistency in trace information I see in-page vs. trace.axd (recall that traditional asp.net outputs identical in-page vs. trace.axd outputs). I would really like to have my in-page trace information consistent with trace.axd (either by removing the traditional asp.net page events or other means). Is there something I am missing?
Quoting directly from the book "MVC 2 in action":
When you called Trace.Write() in Web
Forms, you were interacting with the
Trace- Context class. This exists on
your ViewPage in ASP.NET MVC, but this
isn’t where you would want to write
tracing statements. By the time you’ve
passed the baton over to the view,
there’s no logic there that you’d need
to trace. Instead, you’d like to trace
the logic embedded in your
controllers. You might try to leverage
the TraceContext class in your
controller, but these statements won’t
ever make their way to the list of
messages in the trace log (on your
page or on Trace.axd). Instead, you
can use System.Diagnostics.Trace and
set up your own TraceListeners to
inspect the activity in your
controllers. Alternatively, you can
leverage a more mature logging
framework such as log4net or NLog:
You debug ASP.NET MVC applications
just as you would any .NET
application. Tracing, however, doesn’t
offer as much for MVC. Instead, you
can lean on the built-in
TraceListeners in .NET, or utilize a
good logging library like those
mentioned earlier. Another aspect of
error logging is health monitoring.
Sorry for not answering in my own words, but I think this explanation is spot on :)
Actually, now this can be done. Using glimpse, you can return and use Trace.Write in MVC.
http://getglimpse.com/
Only for ASP.NET MVC 3.0 and up
Instead of using the HttpContext.Current.Trace or the System.Diagnostics.Trace, try using the Controller.HttpContext.Trace ?
The quote doesn't apply to tracing in filters and actions. Even then, it doesn't apply as you can get trace output from OnResultExecuting. It's only OnResultExecuted where it's too late to get trace output.
I was only able to get integrated trace output to work in IIS 7.5 by running my MVC 3 application in Cassini - then integrated tracing started working in IIS 7.5.
I'm investigating some trace anomolies in MVC
You could try to use Html.Action to get the controller to do the tracing for you.
For example, if you need to trace the error from the default Error view, you can use
Html.Action("TraceError", "Error", new { ControllerName = Model.ControllerName, ActionName = Model.ActionName, Exception = Model.Exception })
Then inside your Error Controller, implement the method
public ActionResult TraceError(String ControllerName, String ActionName, Exception Exception)
{
System.Diagnostics.Trace.TraceError("Error Message: {0}", Exception.Message);
// Other tracing statements
}

Resources