Concurrent users and variables - google-app-maker

Need: for multiple users to use the app at the same time, being tracked by their own request id.
I've been using datasouce parameters to hold my "current place" variable, but I'm now uncertain whether that parameter is specific to this instance or if each user is going to overwrite it.
It looks like the apps script script properties is definitely shared between users. And I thought User Properties were being deprecated for apps script anyway.
How do you ensure concurrent use of your apps don't step on each others toes?
By script properties I mean these kinds of things:
function setProp(property, value) {
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperty(property, value);
}
function getProp(property) {
var scriptProperties = PropertiesService.getScriptProperties();
var value = scriptProperties.getProperty(property);
return value;
}
whereas when I'm using datasource properties I mean:
var runID = app.datasources.requests.properties.current;

Related

Session values cant be obtained between two different web api calls

I have two Web API methods called in different cases. I have used the SetString method and the value is set in method 1 but when the 2nd method is called for other cases, accessing the value using the GetString method it returns the value as null.
public string Method1(string args)
{
HttpContext.Session.SetString("key", "value"); // value is set in this method.
}
public string Method2(string args)
{
string value = HttpContext.Session.GetString("key"); // value is obtained as null here
}
Any suggestions to resolve this issue. I have added controller manually in the blazor server-side application for WebAPI call.
options.Cookie.SameSite = SameSiteMode.None must be used to allow cross-site cookie use.
https://learn.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-5.0
Startup#ConfigureServices
services.AddSession(options => {
options.Cookie.SameSite = SameSiteMode.None;
options.IdleTimeout = TimeSpan.FromSeconds(600); // 10 minutes
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
Startup#Configure
app.UseSession();
The order of middleware is important. Call UseSession after UseRouting and before UseEndpoints. See Middleware Ordering.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-5.0
If you run your app on multiple instances, you'll need to choose a strategy. Storing sessions using Distributed Cache is preferable. More info: https://dzone.com/articles/aspnet-core-session-storage-strategies
Another way of solving multiple server issue, is to use sticky sessions on your load balancer. This is not recommended because of the risc of uneven spread of load.
If you are able to get rid of the need for sessions in your app, I would highly recommend that.

Is there any disadvantage to using a dynamic return type on my API endpoints?

I am currently building a web api service using MVC and I am creating the endpoints. For example, my GET endpoint will execute a stored procedure and return the data in JSON format. The model of the data returned can vary in the future and it seems like using a dynamic return type would remove the need of having to change the model and mapping every time that happens. Basically, here is some sample code, do you notice any malpractices in my implementation?
[System.Web.Mvc.HttpGet]
[Route("companies/{id}")]
public dynamic GetCompany([FromUri] int id, string userId)
{
var parameters = new Hashtable
{
{"UserID", userId},
{"CompanyID", id}
};
var result = MyDB.ExecuteSp(CompanyReadByIdSp, parameters);
return result;
}
In fact, this would enable me to transform the object and add whatever I want to it without needing to worry about the model. Is this a bad way of doing things? Thanks ahead.

how to design a custom product builder

I am developing an application for generating estimates on products such as cars.
So, when a car make an model is selected, I need to present various options to the user (options may be in different groups like Wheels, Seating Upholstery, Trunk Accessories)
Depending upon the group, the customer may pick one or more options in that group; if a certain option is selected - some other options may get disabled; not all options apply to every make an model
So, there are several rules to be defined for different groups to indicate what combination is allowed and what is not allowed?
How should I go about designing the database for this and is there a pattern that I can leverage as I develop this application?
I solved a similar requirement with the following structure, rewritten in your terms above:
Parts
Groups
Car
With the following notes:
Parts are standalone in their own right, each with a part number.
A car template is standalone in its own right.
Parts can be added to a option group, and a number of options groups belongs to a car.
An option group cannot exist without a car.
A group can depend on another group
I need to protect against circular references
I started out playing with my model by writing the test case before i wrote the class code (Test Driven Development), which gave me code (in C#) as:
var dieselEngine = new Sku("diesel 2_litre,",1000);
var petrolEngine2 = new Sku("petrol_2_litre",800);
var petrolEngine25 = new Sku("petrol_25_litre",900);
var petrolTurbo = new Sku("petrol_turbo",2000);
var dieselTurbo = new Sku("diesel_turbo",2000);
var car = new Car("myCar");
car.AddGroup("Engines");
car.AddSkuToGroup("Engines", diselEngine);
car.AddSkuToGroup("Engines", petrolEngine2);
car.AddSkuToGroup("Engines", petrolEngine25);
car.AddGroup("Turbos");
car.AddSkuToGroup("Turbos", petrolTurbo);
car.AddSkuToGroup("Turbos", dieselTurbo);
car.SetRequirement(diselEngine, dieselTurbo);
car.SetRequirement(petrolTurbo, petrolEngine2);
car.SetRequirement(petrolTurbo, petrolEngine25);
I add the dependency option on the groups, rather than on the Sku, since a part may exist across multiple cars but may have different dependencies for each specific car.
I have to put everything through the root car object, which will check and enforce all my business rules (such as checking for and protecting against circular references).
Should all access via the car object feel clunky, you could always have the car.AddGroup function return a group to make the code make more sense to read:
var engines = car.AddGroup("Engines");
engines.AddSkuToGroup(diselEngine);
engines.AddSkuToGroup(petrolEngine2);
engines.AddSkuToGroup(petrolEngine25);
But do not forget the business rules can only be enforced by the car, since the car has visibility of all the components. So we always chain up via the root:
class ConfigurableProduct
{
List<Group> groups = new List<Group>();
Group NewGroup(string name)
{
var group = new Group(this, name);
this.groups.Add(group);
return group;
}
bool ContainsSku(string skuId)
{
foreach (var group in this.Groups)
{
if (group.ContainsSku(skuId))
return true;
}
return false;
}
}
class Group
{
Group(ConfigurableProduct parent, string name)
{
this.parent = parent;
this.name = name;
}
string name;
List<string> skuIds = new List<string>();
ConfigurableProduct parent;
void AddSkuToGroup(string skuId)
{
// enforce invariants via parent, call functions as reuqired
if (this.parent.containsSku(skuId))
throw new Exception("SKU already exists in this configurable template, cannot exist twice");
// do other things, like check circular references etc, all via this.parent
}
bool ContainsSku(string toFind)
{
foreach (var skuId in this.skuIds)
{
if (skuId == toFind)
return true;
}
return false;
}
}
For the actual database storage i would worry about persistence last, it could be a text file, MSSQL database, MySQL database, MongoDB, there are so many options.
I find it always useful to concentrate on how i want to use the code in my application, and not the specifics of how the database needs to be used, as the storage can abstracted via a repository interface that returns a class (a plain old POCO class, but in this case we have started to flesh out with business logic to protect against invalid states).
For the front end, you may want to push this all down via JSON to something like angular or knockout that can render the options available dynamically, and show or hide different elements depending on the dependencies between groups.
Working fronted example
I am not sure what front end binding you are using (or if you will only be using razor, in that case you will need to store state on the server and refresh each selection), but I have provided an example using Knockoutjs here: http://jsfiddle.net/g18c/5jt9bwsv/1/ with working dependencies and dynamic javascript object builder.
Loops through provided JSON products by group
Creates calculated fields that change depending on a target dependency
Binds to a view via knockout
The selected SKUs could then simply be passed up to the server, any business rules can also be implemented in the front end javascript.
Of course anything data that is sent from the client to the server would need to be validated by building up the product graph on the server and checking that the provided SKUs are valid (i.e. you wouldn't want to allow a Diesel Turbo to be selected for a Petrol Engine).

Entity Framework: Many to Many Relationship

I have two tables with a Many-To-Many relationship like this:
User(emailaddress, Name)
UserAlerts(emailaddress, AlertId)
Alert(AlertId,Title)
Alerts have already been added to the database. When inserting a new user, I am doing a lookup on the AlertRepository. The problem is, Instead of creating a record in the User and the UsertAlerts tables only, its also adding an extra Alert record.
I am using the following code:
public ActionResult Register(UserModel model, int[] Alerts)
User user = new MidTier.Models.User();
user.Name = model.Name;
user.EmailAddress = model.EmailAddress;
if (Alerts!=null)
{
IRepository<Alert> alertRepository = new AlertRepository();
foreach (int alertId in Alerts)
{
Alert alert = alertRepository.First(a=>a.ID== alertId);
alertRepository.Detach(alert);
if (alert != null)
{
alert.Enabled = true;
user.Alerts.Add(alert);
}
}
}
userRepository.Attach(user);
userRepository.Add(user);
userRepository.Save();
Why don't you try to search little bit before you ask a question? This problem is asked several times per week. In your previous question I said you that you should use same context for loading Alert and storing User. You didn't do it and complicated whole situation.
The context doesn't know anything about existence of the alert. Once you call Add for user it will add all entities which are not tracked yet. There are three ways to solve this:
Use the same context in both repositories and do not detach alerts. Because of loading alerts, context will know about their existence and doesn't insert them again.
If you don't use the same context for loading you must attach the Alert to the new context before you add it to User. That is hard to do when you wrap EF code to repositories.
If you don't use the same context and you will not attach Alert to the new context before you add it to User you must modify your Add method for User and after adding User to the context you must iterate every alert and change its state to Unchanged.

In ASP.NET (server side), how can I uniquely identify one browser window from another which are under the same cookiedbased sessionId

The users of my web application may have more than one browser window (or tab) open and pointed to the same page. We're using cookie based session id's, and the user will usually work within the same session id in both browsers/tabs. I would like to be able to uniquely identify which browser window (and tab) that requested an ASP.NET page (in order to make sure, that data stored in the session does not get mixed up).
(e.g. I would be happy if the browser would generate and send a window/tab-id with the http request, as it publishes HTTP_USER_AGENT)
Any ideas?
--thomas
If I was going to implement something like this I would probably start with a Dictionary<Type, List<Guid>> and store this in the users session. I would also probably make this be a custom type that delegates the dictionary and have a factory method that works similar to
public Guid GeneratePageIdentifier(Page thepage)
{
var guid = Guid.New();
if(_dictionary[thepage.GetType()] == null)
_dictionary[thepage.GetType()] = new List<Guid> { guid };
else
((List<Guid>)_dictionary[thepage.GetType()]).Add(guid);
return guid;
}
Then embed the guid that's returned from that method on the VIewState of the page. On your page methods that execute actions that you need to validate which page it is you would be able to validate that guid is inside the collection do something. You might also want to implement a custom a type with a guid property to enscapulate more information about why you're doing this or what you need for it to be meaningful.
The Viewstate on each page will be different, maybe you can use some kind of unique identifier created on every page loaded?
It is by default not possible due to the stateless nature of the web, but you could add a "page identifier" that gets generated with each opened page and transmitted for every action.
I'd recommend that you refactor the application in a way that those mixups can't happen, no matter from which page/tab/window the request originates.
As Mark Redman said, you can use Viewstate + Session in order to store values specific to the page.
ViewState is good for storing the key (string), Session for storing whatever type of complex objects.
Use the ViewState or a hidden field in order to load at the first call a GUID.
public string PageUid
{
get
{
if (ViewState["UID"] == null)
ViewState.Add("UID", Guid.NewGuid().ToString());
return ViewState["UID"].ToString();
}
}
Then use the session to get/set your values using this key:
string MyPagesessionVariable
{
get
{
if (Session["MYVAR" + PageUid] == null)
{
Session["MYVAR" + PageUid] = "VALUE NOT SHARED WITH OTHER TABS/WINDOWS";
}
return Session["MYVAR" + PageUid];
}
set
{
Session["MYVAR" + PageUid] = value;
}
}

Resources