Using Kendo Web UI Schedular Using SignalR & MVC - asp.net-mvc

Hi we are currently working on kendo UI Scheduler and wanting to make the scheduler real time using SignalR.
What we are trying to achieve is if 2 customers are viewing the scheduler at the same time and client 1 makes a booking the 2nd client will see that someone has booked that particular time slot so that double booking does not occur.
also if a client makes a booking on the scheduler then the admin will also see the booking in real time.
currently we have the scheduler inserting to the database with no problem, from there we want to broadcast the newly created booking to all others who are viewing the scheduler at that time.
can this be done? if so any ideas.
i can supply code to what we have done upto now if need required.
my thoughts are to broadcast the new scheduler booking in the ActionScript method then broadcast the new booking to clients from there.
public ActionResult Tasks_Create([DataSourceRequest]DataSourceRequest request, TaskViewModel task)
{
if (ModelState.IsValid)
{
using (var sampleDB = new SampleEntities())
{
//Create a new Task entity and set its properties from the posted TaskViewModel
var entity = new Task
{
TaskID = task.TaskID,
Title = task.Title,
Start = task.Start,
End = task.End,
Description = task.Description,
RecurrenceRule = task.RecurrenceRule,
RecurrenceException = task.RecurrenceException,
RecurrenceID = task.RecurrenceID,
IsAllDay = task.IsAllDay,
OwnerID = task.OwnerID
};
sampleDB.Tasks.Add(entity);
sampleDB.SaveChanges();
task.TaskID = entity.TaskID;
}
}
(i was thinking to broadcast the new booking here using signalr ????)
return Json(new[] { task }.ToDataSourceResult(request, ModelState));
}

Yes, it can be done (and broadcasting from your controller action is a reasonable approach). You'll probably want to create a group for people who are looking at the same data.
Take a look at this section in the docs on how to call client hub methods from non-hub classes.

Related

Time out 500 error on Edmx

I developed a website using Asp.Net MVC and Edmx database and I published this website on azure and my database is also on azure and I've a functionality on website that uploads excel record into database and that excel sheet contain almost 18000 records every time I upload that sheet it throw Timeout error after some time so what should I do.
Initially I was not using any command Timeout but after doing some research I'm using this in constructor
public ProfessionalServicesEntities()
: base("name=ProfessionalServicesEntities")
{
this.Database.CommandTimeout = 10000;
//this.Database.CommandTimeout = 0; //I tried this too.
//((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 3600;
}
Here is the code of
function :-
public void SaveEquipments(IEnumerable<EquipSampleEntity> collection)
{
using (ProfessionalServicesEntities db = new ProfessionalServicesEntities())
{
string modelXml = XmlSerialization.ListToXml(collection.Where(x=>x.Type == Model).ToList());
string accessoryXml = XmlSerialization.ListToXml(collection.Where(x => x.Type == Accessory).ToList());
db.ImportEquipmentFile(modelXml, accessoryXml);
}
}
here is context file code for SP:-
public virtual int ImportEquipmentFile(string modelXml, string accessoryXml)
{
var modelXmlParameter = modelXml != null ?
new ObjectParameter("ModelXml", modelXml) :
new ObjectParameter("ModelXml", typeof(string));
var accessoryXmlParameter = accessoryXml != null ?
new ObjectParameter("AccessoryXml", accessoryXml) :
new ObjectParameter("AccessoryXml", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("ImportEquipmentFile", modelXmlParameter, accessoryXmlParameter);
}
You may be processing the excel on upload itself and processing it row by row. You have two options, one is to schedule a background job to pickup the upload file and insert it to DB and complete the request.
Next option is to read the whole file in one go and do a single bulk insert into the DB.
There are too many things that can cause this. In Azure App Service there is a Front-end which has a timeout of 240 seconds. If your application takes more time, then you might run into this. This could be one of the probable causes.
In order to understand what is happening. Enabled Web Server Logging and Failed Request Tracing.
See this for how to proceed further: https://learn.microsoft.com/en-us/azure/app-service-web/web-sites-enable-diagnostic-log

UCommerce Prevent Users from adding new items during checkout

I have an Ecommerce website build with UCommerce. During the checkout process the user will be redirected to the payment portal for the payment.
I want to prevent users from adding new items in the basket while the user is in the payment portal. My current solution is to save the basket to a Session before redirecting the user to the payment portal.
Session["checkoutOrder"] = TransactionLibrary.GetBasket(!TransactionLibrary.HasBasket()).PurchaseOrder;
How can I overwrite the current basket with the one in the Session After the payment? This is to revert the basket to its original state before the payment.
I tried this:
[HttpPost]
public ActionResult ExecutePayment()
{
var order = Session["checkoutOrder"] as PurchaseOrder;
order.Save();
...
}
But I'm getting an error on order.Save():
Batch update returned unexpected row count from update; actual row count: 0; expected: 1
I'd just add to this as well that your Session["orderInProcess"] is an anti pattern in uCommerce. You may run into nasty exceptions as you're persisting NHibernate entities through requests which can/will lead to Session disposed exceptions. It may also lead to the initial exception that you're experiencing as you're actually by-passing the sesssion state of NHibernate.
Just use TransactionLibrary.GetBasket(!TransactionLibrary.HasBasket()).PurchaseOrder; every time you're retrieving your basket. NHibernate will take care of caching the order for you.
Then you can use order properties to save the state you're in.
var basket = TransactionLibrary.GetBasket(!TransactionLibrary.HasBasket()).PurchaseOrder;
basket["CheckoutInProcess"] = "True";
Best regards
Morten
I handled this differently since I have no way of reverting back the basket to its original state.
I decided to block the user from adding items in the basket when the payment is in process.
I created a session Session["orderInProcess"]=true before I redirect the user to the payment gateway.
Now every time the user tries to add a new item in the basket, I will check first if his current order is in process. like so:
[HttpPost]
public ActionResult AddToBasket(string sku, string quantity, string variant = null)
{
if (Session["orderInProcess"] != null)
{
if (bool.Parse(Session["orderInProcess"].ToString()))
{
return Json(new
{
Success = false,
ErrorMessage = "Order is currently in process."
});
}
}
.....
}
I hope this helps.

How to initialize and persist Castle ActiveRecordStarter per session for multi tenancy apps?

I am using Castle ActiveRecord in my Asp.net / MVC 2 / Multi-tenancy application with SQL Server as my backend.
For every user logging in, the app loads the corresponding DB, dynamically at run time like below:
IDictionary<string, string> properties = new Dictionary<string, string>();
properties.Add("connection.driver_class", "NHibernate.Driver.SqlClientDriver");
properties.Add("dialect", "NHibernate.Dialect.MsSql2005Dialect");
properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
properties.Add("proxyfactory.factory_class", "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
properties.Add("connection.connection_string", strDBConnection);
InPlaceConfigurationSource source = new InPlaceConfigurationSource();
source.Add(typeof(ActiveRecordBase), properties);
ActiveRecordStarter.Initialize(new System.Reflection.Assembly[] { asm1 }, source);
The strDBConnection string comes from another small database that holds the user info, corresponding DB, etc.
Scenario:
When a user logs in, his DB gets loaded, he can do his CRUD jobs -- No Probs !
Another user logs in (from another remote machine) his DB gets loaded -- No Probs !
Now, when the first user reads from DB, he sees new data from the second user's DB
My little understanding for this behavious is : ActiveRecordStarter is a Static object.
Could someone help me with a solution for this situation ?
The expected behaviour:
each user should access his own DB only, securely, in parallel / at the same time.
Thanks a lot !
ActiveRecordStarter.Initialize should only be called once in your app (in Application_Start in Global.asax).
To achieve what you want, create a class that inherits from NHibernate.Connection.DriverConnectionProvider:
public class MyCustomConnectionProvider : DriverConnectionProvider
{
protected override string GetNamedConnectionString(IDictionary<string, string> settings)
{
return string.Empty;
}
public override IDbConnection GetConnection()
{
// Get your connection here, based on the request
// You can use HttpContext.Current to get information about the current request
var conn = Driver.CreateConnection();
conn.ConnectionString = ... // Retrieve the connection string here;
conn.Open();
return conn;
}
}
Then set the connection.provider property to the name of your class:
properties.Add("connection.provider", "MyCompany.Domain.MyCustomConnectionProvider, MyCompany.AssemblyName");

Entity framework and transaction in asp.net mvc application

I have question about managing transaction in asp.net application.
For example i have application for planning vacations.
Controller has form to approving vacations.
One user - click save and approve vacation ---- employee which want vacation has - 1 day
second user - clik save and approve vacation and ?
//pseudocode
public void ApproveVacation(int vacationId)
{
//pull vacationdata from db
var vacation = _dbContext.Vacations.FirstOrDefault(x => x.Id == vacationId);
if (vacation != null && vacation.State != approved) //
{
using (TransactionScope scope = new TransactionScope())
{
vacation.state = approved;
vacation.Employee.Days = -1;
_dbContext.saveChanges();
scope.complete();
}
}
}
And question is simple, is transaction enough for this scenario or I must use one of concurency technique?
Thanks
EDIT : Context is created one per request.
Transaction handles atomicity of the operation so if operation modifies multiple database records it will always result in consistent state where all records are correctly modified (if operation succeeds) or all changes are rolled back (if operation fails).
Concurrency handles possible modification of the same record by multiple processes / users because both could load original version of the record but one could save it first so when the second process tries to save a record it can silently override previous changes.
So what are you trying to handle in your code?
You already have an implicit transaction when calling 'SaveChanges' so there's no need for a transaction scope.
And also, if you would change several items you would need to start the TransactionScope before you retrieve the data.

Repository Connection Pooling

I'm in a hoo-ha with my boss as I can't shift to using newer technologies until I have proof of some outstanding issues. One of the main concerns is how repositories deal with connections. One of the supposedly largest overheads is connecting and disconnecting to/from the database. If I have a repository where I do the following:
public ContractsControlRepository()
: base(ConfigurationManager.ConnectionStrings["AccountsConnectionString"].ToString()) { }
with the class like so:
public class ContractsControlRepository : DataContext, IContractsControlRepository
with functions like:
public IEnumerable<COContractCostCentre> ListContractCostCentres(int contractID)
{
string query = "SELECT C.ContractID, C.CCCode, MAC.CostCentre, C.Percentage FROM tblCC_Contract_CC C JOIN tblMA_CostCentre MAC ON MAC.CCCode = C.CCCode WHERE C.ContractID = {0}";
return this.ExecuteQuery<COContractCostCentre>(query, contractID);
}
Now if in my controller action called _contractsControlRepository.ListContractCostCentres(2) followed immediately by another call to the repository, does it use the same connection? When does the connection open in the controller? When is it closed?
Cheers
EDIT
I'm using hand-written LINQ as suggested by Steve Sanderson in his ASP.NET MVC book.
EDIT EDIT
To clarify, I'm using LINQ as my ORM, but I'm using raw SQL queries (as shown in the extract above) for querying. For example, here's a controller action:
public ActionResult EditBusiness(string id)
{
Business business = _contractsControlRepository.FetchBusinessByID(id);
return View(business);
}
I'm not opening/closing connections.
Here's a larger, more complete extract of my repo:
public class ContractsControlRepository : DataContext, IContractsControlRepository
{
public ContractsControlRepository()
: base(ConfigurationManager.ConnectionStrings["AccountsConnectionString"].ToString()) { }
public IEnumerable<COContractCostCentre> ListContractCostCentres(int contractID)
{
string query = "SELECT C.ContractID, C.CCCode, MAC.CostCentre, C.Percentage FROM tblCC_Contract_CC C JOIN tblMA_CostCentre MAC ON MAC.CCCode = C.CCCode WHERE C.ContractID = {0}";
return this.ExecuteQuery<COContractCostCentre>(query, contractID);
}
Then ContractsControlRepository is instantiated in my controller and used like _contractsControlRepository.ListContractCostCentres(2). Connections aren't opened manually, DataContext deals with that for me.
Without knowing the details of your ORM and how it connects the SQL database drivers will connection pool. When a connection is closed it is released back to the pool and kept open for X number of seconds (where X is configurable). If another connection is opened and all the parameters match (the server name, the application name, the database name, the authentication details etc.) then any free, but open connections in the pool will get reused instead of opening a brand new connection.
Having not read the book in question I don't know what "manual linq" actually is. If it's manual means you're getting the tables back youself then obviously you're doing the connection open/close. Linq to SQL will use a new connection object when a statement is finally executed at which point connection pooling comes into play - which means a new connection object may not be an actual new connection.

Resources