jQuery Ajax – tips

jQuery Ajax is async by nature. We use to set a flag “async:false” if we need to make Ajax call sync (non-blocking). This feature has been deprecated. Here is a compile list of Ajax using jQuery;

Alternative to “async: false” for successive AJAX calls

Handling Sequential AJAX Calls using jQuery

Multiple Simultaneous Ajax Requests (with one callback) in jQuery

jQuery callback for multiple ajax calls

jQuery.when understanding

jQuery Promises – Taking action .when() multiple ajax calls are complete

Dapper – ORM example list

I am using EF for most of my ORM and data access. Recently I have tries Dapper and started liking it because of its simplicity and small footprint. Here is a list of example;

Using Dapper to fill a dataset;

Dapper returns a IDataReader when we use the ExecuteReaderAsync method. More information on this addition can be found here and here.

Use Nuget package to add Dapper. Add this to your Main class for quick demo;

static IDbConnection dbConn = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlServerConnString"].ConnectionString);

Here you go with DataSet example using Dapper;

public async Task<DataSet> GetUserInformationOnUserId(int UserId)
{
    var storedprocedure = "usp_getUserInformation";
    var param = new DynamicParameters();
    param.Add("@userId", UserId);
    var list = await SqlMapper.ExecuteReaderAsync(dbConn, storedprocedure, param, commandType: CommandType.StoredProcedure);
    var dataset = ConvertDataReaderToDataSet(list);
    return dataset;
}

Here is conversion to dataset method;

public DataSet ConvertDataReaderToDataSet(IDataReader data)
{
    DataSet ds = new DataSet();
    int i = 0;
    while (!data.IsClosed)
    {
        ds.Tables.Add("Table" + (i + 1));
        ds.EnforceConstraints = false;
        ds.Tables[i].Load(data);
        i++;
    }                    
    return ds;
}

How to map class names to class properties with dapper

Manually map column name with class properties

Does Dapper supports .NET DataSets

Get base url in javascript

If you are constructing your URL like this;

message += '<br><a href=/Project/GetFileData?documentId=' + response.Data.vm.DocumentId + '>' + response.Data.vm.FileName + '</a>';

You will get results like this;

https://www.foo.com/Project/GetFileData?1234

This will not work on a web site that has following URL;

https://www.foo.com/demo/Project/GetFileData?1234

To fix this problem in ASP.NET Core, use this;

var url = '@Url.Content("~");
message += '<br><a href=' + url + '/Project/GetFileData?documentId=' + response.Data.vm.DocumentId + '>' + response.Data.vm.FileName + '</a>';

Other useful function to find URL are;

var url = window.location.origin;
var host = window.location.host;
var pathArray = window.location.pathname.split( '/' );

Return a Json Object from another function call

When we try to capture a value from called method we get undefined. The reason is that data hasn’t been fetched yet. Fetch takes some time to make the call and send back the result, and it’s asynchronous, Here is an example;

function getApi() {
  var obj;

  fetch("https://foo.apicode.com/posts/1")
    .then((res) => res.json())
    .then((data) => (obj = data));

  return obj;
}

let x = getApi();
console.log(x);

When we console.log the value, getApi() didn’t finish yet, therefore didn’t set the obj

The fetch method is asynchronous, so obj is undefined because the code is going to the next instruction without waiting the fetch. We can simply use async/await method that is a great way to make asynchronous calls because await will wait for the result before going to the next instruction.

async function getApi() {

      const response = await fetch("https://foo.apicode.com/posts/1")
        
      const obj = await response.json()
      
      return obj;
    }

(async() => {
   let x = await getApi();
   console.log(x);
})()

Resources

https://stackoverflow.com/questions/49432579/await-is-only-valid-in-async-function

Store and Read Objects from Session in ASP.NET Core

Here you go;

In your Startup.cs, under the Configure method, add the following line:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSession();
}

And under the ConfigureServices method, add the following line:

public void ConfigureServices(IServiceCollection services)
{
  //Added for session state
  services.AddDistributedMemoryCache();

  services.AddSession(options =>
  {
  options.IdleTimeout = TimeSpan.FromMinutes(10);               
  });
}

The simple method to store and read data from session is;

# In a class;
Session.SetString("Email", "foo.com"); //store data
Session.GetString("Email"); //read data

# In Razor pages
@using Microsoft.AspNetCore.Http; 
string CustomerEmail = String.Empty;
@if (Context.Session.GetString("Email") != null)
 {
     CustomerEmail = Context.Session.GetString("Email").ToString();
 }
}

# You can use it in Razor markup 
<ul class="navbar-nav mr-auto float-right">
   <li class="nav-item">
      <span class="navbar-text text-light">Hello @CustomerEmail</span>
   </li>

</ul>

In order to store complex objects in your session in .NET Core, follow the following steps:

Create a model class of your object type (in your case EmployeeDetails):

public class EmployeeDetails
{
    public string EmployeeId { get; set; }
    public string DesignationId { get; set; }
}

Then create a SessionExtension helper to set and retrieve your complex object as JSON:

public static class SessionExtensions
{
  public static void SetObjectAsJson(this ISession session, string key, object value)
   {
     session.SetString(key, JsonConvert.SerializeObject(value));
   }

   public static T GetObjectFromJson<T>(this ISession session, string key)
   {
     var value = session.GetString(key);
     return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
   }
}

Then finally set the complex object in your session as:

var employee = new EmployeeDetails();
employee.EmployeeId = "1";
employee.DesignationId = "2";

HttpContext.Session.SetObjectAsJson("EmployeeDetails", employee);

To retrieve your complex object in your session:

var employeeDetails = HttpContext.Session.GetObjectFromJson<EmployeeDetails>("EmployeeDetails");
int employeeID = Convert.ToInt32(employeeDetails.EmployeeId);
int designationID= Convert.ToInt32(employeeDetails.DesignationId);

My session was not working. it turns out that it relates to GDPR issues. Three fixes;

FIX-I

The first fix is to provide user a login page and let him accept cookies policy.

If you don’t provide a login page and still want to configure sessions in ASP.NET Core, you need these two fixes in Startup.cs file;

Fix-II Startup.cs file ConfigureServices method. Add this line;

 services.AddSession(options =>
 {
    options.Cookie.IsEssential = true;
 });

Fix-III Startup.cs file Configure method, comment this line;

//app.UseCookiePolicy();

The most common fix is FIX-I. For testing I choose Fix-II and session started working.

Sources

https://andrewlock.net/session-state-gdpr-and-non-essential-cookies/