Solved: Fluent Nhibernate SaveOrUpdate not updating DB

I had a scenario were all the select commands were working but all update commands (including delete) effecting db were not working. No errors or exceptions were being returned so it was quite hard to understand what it was. However finally, I realised that the problem was that nhibernate often commits updated once the session has been flushed.

To test if this is the issue:

After the SaveOrUpdate() command, I tried the session.flush(), and the db saved successfully.

To fix, visit the global.asax and in the Application_EndRequest add:

first add reference to:

using NHibernate;
using NHibernate.Context;

Then add the Application_EndRequest() as below:

protected void Application_EndRequest()

{

ISession mySession = ManagedWebSessionContext.Unbind(HttpContext.Current, SessionManager.SessionFactory);

if (mySession != null)
{

mySession .Flush();
mySession .Close();

}

}

If you are using transactions, I would suggest checking from active session transactions before flushing the session:

protected void Application_EndRequest()

{

ISession mySession = ManagedWebSessionContext.Unbind(HttpContext.Current, SessionManager.SessionFactory);

if (mySession != null)
{

if (mySession .Transaction != null && mySession .Transaction.IsActive)
{

mySession .Transaction.Rollback();

}
else
{

mySession .Flush();

}
mySession .Close();

}

}

Error: [System.Threading.ThreadAbortException] = {Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.}

When trying to download a file using similar code to the below, I kept on getting the ThreadAbortException:

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader(“content-disposition”, attachment);
HttpContext.Current.Response.ContentType = “text/csv”;
HttpContext.Current.Response.AddHeader(“Pragma”, “public”);

var sb = new StringBuilder();

foreach (string row in rows)
{
sb.Append(row + “\r\n”);
}

HttpContext.Current.Response.Write(sb.ToString());
HttpContext.Current.Response.End();

Even if I surround it with try and catch, I was not solving my issue since I simply do not want the exception to occur and not go around it. After some research I discovered that reason was that Response.End ends the whole page execution and fires the Application_EndRequest event. Cutting the story short, replacing Response.End with the below solved my issue since it does not fire the Application_EndRequest event and continues to execute my page:

HttpContext.Current.ApplicationInstance.CompleteRequest();

Forcing SSL on ASP.NET from http to https and vice-versa

SSL

Lets assume we have a shopping chart web app, to create a safe environment for your buyers you need to run the payment page on https. So here is what we will need to do….

In your master page (assuming you have one), read through and paste the following code in the page load or page init:

protected void Page_Load(object sender, EventArgs e)
{

//if on https, secure = true;

bool secure = HttpContext.Current.Request.IsSecureConnection;

//Path of the page which requires SSL (https) – CHANGE TO OWN PATH

string paymentPagePath = “/PaymentGateway/default.aspx”;

// Server name or localhost if running locally

string serverName = Request.ServerVariables[“SERVER_NAME”];

// Path of the current page
string scriptName = Request.ServerVariables[“SCRIPT_NAME”];

// Query String if any
string queryString = Request.ServerVariables[“QUERY_STRING”];

// If we are on the page which requires SSL
if (absolutePath.Contains(paymentPagePath))
{

// If it is not currently using https
if (!secure)
{

if (Request.ServerVariables.Get(“HTTP_CLUSTER_HTTPS”) == null)
{

string xredir__, xqstr__;

// Build redirect Link using https 

xredir__ = “https://” + serverName;
xredir__ += scriptName;
xqstr__ = queryString;

if (xqstr__ != “”)
xredir__ = xredir__ + “?” + xqstr__;

// Redirect to same page using https

Response.Redirect(xredir__);

}

}

}

 // else if not of page which requires SSL

// if page is using SSL, we need to redirect to http
else if (secure)
{

string xredir__, xqstr__;

xredir__ = “http://” + serverName;
xredir__ += scriptName;
xqstr__ = queryString;

if (xqstr__ != “”)
xredir__ = xredir__ + “?” + xqstr__;

// Redirect to same page using http and not https

Response.Redirect(xredir__);

}

}

Securing a path/folder in an ASP.NET Web Application

Create or open your global.asax and open the code behind.

In your Application_AuthenticateRequest method create a request to check if user is logged in and check if his role is entitiled to view the path you are securing. In my case I am using Windows authentication, so I will use User.Identity.Name and if it is null it means no user is logged in. Then we will request the url path the user is requesting to check if the user is trying to access an unauthorized path. If so, we redirect him back to an error page, home page or wherever you prefer.

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
try
{

//Check if it contains our secure folder or path part

if (requestPath.Contains(“/Secure/”))

{

//Check if username is null (if null, means not logged in)
if (!string.IsNullOrEmpty(Context.User.Identity.Name))
{

bool allowed = false; // create a statement to see if user is in a role that allows or restricts access to this secure path

//Request URL in browser
string requestPath = Request.Url.AbsolutePath;

//checks if the user does not have access (!allowed means NOT ALLOWED)

if (!allowed)
{

//Redirect to error page

Response.Redirect(“ErrorPage.aspx”);
}

}

}
}
catch (Exception ex)
{

//An exception might occure if the User.Identity.Name is not set (empty / not logged in)
Response.Redirect(“ErrorPage.aspx”);
}

}

Quickly create a 12-digit Number Generator Securely in C#

Step 1:

Add Reference to your project to System.Security

Step 2:

In you class add:

using System.Security.Cryptography;

Step 3:

In your class add the following  method using RNG encryption service provider to enforce secuity on your random number:

public long GetNextInt64()
{
var bytes = new byte[sizeof(Int64)];
RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
Gen.GetBytes(bytes);

long random = BitConverter.ToInt64(bytes, 0);

//Remove any possible negative generator numbers and shorten the generated number to 12-digits
string pos = random.ToString().Replace(“-“, “”).Substring(0, 12);

return Convert.ToInt64(pos);
}

 

Easy huh??

Error during serialization or deserialization using the JSON JavaScriptSerializer

Scope: 

Returning a DataTable from a WebMethod to JavaScript using C#

WebMethod in code behind:

[WebMethod(BufferResponse = false, CacheDuration = 5)]
public static string GetUsers()
{

//Using Subsonic //Replace with your queries to return a dataset
System.Data.DataSet users= DB.Select().From(Tables.Users).ExecuteDataSet();

return users.GetXml();

}

JavaScript:

function getUsersUpdate() {
$.ajax({
type: “POST”,
url: “default.aspx/GetUsers”,
data: ‘{}’,
contentType: “application/json; charset=utf-8”,
dataType: “json”,
success: OnCompleteSuccess,
failure: OnCompleteFailure,
error: OnCompleteError
});
return false;
}

function OnCompleteSuccess(response)
{
var xmlDoc = $.parseXML(response.d);
var xml = $(xmlDoc);
alert(xml);
}

function OnCompleteFailure(response) {
alert(“Failed: ” + response.reponseText);
}
function OnCompleteError(response) {
alert(“Error Occurred: ” + response.responseText);   //This is where the JSON serialization error is caught
}

Reason for error:

Your DataSet if returning large amount of JSON data while the web.config is configured to allow a max amount of JSON serialization data.

Solution to error:

Remove the max amount of data allowed in the web.config to cater for large amount of JSON data.

In the Web.Config:

Under the <system.web> </system.web> copy and paste the following configs:

<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength=”99999999″/>
</webServices>
</scripting>
</system.web.extensions>

P.S: Make sure that under the <configsection> within the <sectiongroup> you have one section similar to the below:

<section name=”jsonSerialization” type=”System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ requirePermission=”false” allowDefinition=”Everywhere”/>

if not, add that too.

Error: NHibernate.LazyInitializationException was unhandled by user code

Error:

When using Fluent Nhibernate I have encountered several times the following exception:

NHibernate.LazyInitializationException was unhandled by user code

In my situation, the error was showing up when I try to get details from a referenced  column. For instance, from a movies table I have several columns, one of which was CategoryID. In my details view, I wanted to display CategoryName rather than CategoryId so my code looked similar to:

string Category = movie.Category.Name.toString();

That’s when the error was coming up stating that the session was closed. However, when using:

string Category = movie.Category.Id.toString();

Cause:

The last example when I was getting the Id, the error was not fired since the CategoryId is within the same table and thus the session would be open. However, when attempting to get the Category Name, the session would be closed since that session was opened specifically for the movie table.

Solution:

To solve this I simply modified a line of code in my mapping class where I was adding the reference and added the fetch join:

before:

Id(x => x.Id);

References<Category>(x => x.CategoryId, “CategoryId”);

After:

Id(x => x.Id);

References<Category>(x => x.CategoryId, “CategoryId”).Fetch.Join();

MVC Passing Parameters from one view to another through Query Strings

Pass Parameter to another view of another controller:

In view:

@Html.ActionLink(“Movies”, “Index”, “Movie”, new { CategoryId = item.Id}, null)

Where:

  • 1st par “Movies” refers to the link text visible to user
  • 2nd par “Index” is the page you want to link to in the other view
  • 3th par “Movie” is the other View folder you want to link to
  • 4th par is the actual parameter you want to pass, in this case we will be passing category Id to filter the movie list by category

 

In the Movie Controller where we will retrieve the Query String:

public ActionResult Index(int CategoryId)
{

return View(new GetMoviesByCategory(CategoryId);  //replace text in brackets with own methods or preferences.

}

P.S Make sure Parameters are the same (CategoryId) in both View and Controller. You can also pass and assign a parameter manually by replacing item.Id with the CategoryId for instance:

new { CategoryId = 5 }

LINQ for Nhibernate

References Required:

  • using Domain;   //this is the folder where your entities are found
  • using NHibernate;
  • using NHibernate.Criterion;

Other Requirements:

  • Nhibernate / Fluent Nhibernate
  • Linq for Nhibernate
  • Nhibernate Session Helper (can find ready ones on the internet)

1. Return a row by integer Id

public Movies GetById(intId)
{

using(ISession session = NHibernateHelper.OpenSession())

return session.Get<Icon>(Id);

}

2. Return a simple IList<> / Return all rows in a table:
public IList<Movies> GetAll()

{
using(ISession session = NHibernateHelper.OpenSession())

return session.CreateCriteria(typeof(Movies)).List<Movies>();

}

3. Return an IList<> with a WHERE clause:

public IList<Movies> GetMoviesByCategory(int CatId)

{
using(ISession session = NHibernateHelper.OpenSession())

return session.CreateCriteria(typeof(Movies)).Add(Restrictions.Eq(“CategoryId”, CatId)).List<Movies>();

}

4. Return an IList<> with a 3-way JOIN and WHERE clause

public IList<MovieImages> GetMovieImagesByMovieCategory(int CatId)
{

IList<Movie> movies = GetAllMovies(); //Change with your query
IList<MovieCategory> categories = GetAllCategories(); //Change with your query
IList<MovieImages> images = GetAllImages(); //Change with your query

using(ISession session = NHibernateHelper.OpenSession())

return (from mi in images
join m in movies on mi.Movie.Id equals m.Id
join c in categories on m.CategoryId.Id equals c.Id
where c.Id == category.Id
select mi).ToList<MovieImages>();

}

5.Convert List to IList<>

IList<MovieImages> list = myNormalList.ToList<MovieImages>(); //myNormalList would be a common List()

Restart an ASP.NET application programmatically without editing the web.config ( Reset IIS Cache)

Several times I would be working on a site and some data would not change due to session variables or the .NET cache. This can’t be eliminated by clearing the browser cache but would need the whole ASP.NET application to be restarted to clear all sessions and cache. A traditional way of doing so is to edit the web.config slightly (a space, comma, fullstop would do the trick) … however this was happening often so I decided to restart my application automatically through my code. To do so, I used the Global.ascx on application_start and added this simple line of code which restarts the ADO.NET application:

System.Web.HttpRuntime.UnloadAppDomain();