Changing property after specific time in ASP Core MVC - asp.net

I'm working on a subscription-based system developed using Asp Core 3 MVC and Sql Server. The payment is handled externally, not linked to the application in any way. All I need to do in the application is to check the user's status, that is managed by an admin. When a user registers the status will be Pending, when the admin approves the user, Approval Date will be saved in the database, and the status will be changed to Approved.
The tricky thing for me is that I want the application to wait for 365 days before it changes the user status to Expired. I've no idea from where to start this part and would appreciate your help.

The simplest way i can think of without using hosted services is to add a check on user login that subtracts the approval date from today's date and check if the difference is equal or greater than 365 days
Something like this:
if ((DateTime.Now - user.ApprovalDate).TotalDays >= 365)
{
//Mark the user as expired...
}

You really shouldn't trigger a background thread from your main application code.
The correct way to do this is with a background worker process that has been designed specifically for this scenario.
ASP.NET Core 3 has a project type that is specifically for this, and will continue to run the back ground and can be used for all of your maintenance tasks. You can create a worker process using dotnet new worker -o YourProjectName or selecting Worker Service from the project selection window in Visual Studio.
Within that service you can then create a routine that will be used to determine if the user has expired. Encapsulate this logic in a class that makes testing easy.
Working repl has been posted here.
using System;
public class MainClass {
public static void Main (string[] args) {
var user = new User(){ ApprovedDate = DateTime.Today };
Console.WriteLine (UserHelper.IsUserExpired(user));
// this should be false
user = new User(){ ApprovedDate = DateTime.Today.AddDays(-180) };
Console.WriteLine (UserHelper.IsUserExpired(user));
// this should be false
user = new User(){ ApprovedDate = DateTime.Today.AddDays(-365) };
Console.WriteLine (UserHelper.IsUserExpired(user));
// this should be true
user = new User(){ ApprovedDate = DateTime.Today.AddDays(-366) };
Console.WriteLine (UserHelper.IsUserExpired(user));
}
}
public class User {
public DateTime ApprovedDate {get; set;}
}
public static class UserHelper
{
public static bool IsUserExpired(User user){
//... add all the repective logic in here that you need, for example;
return (DateTime.Today - user.ApprovedDate.Date).TotalDays > 365;
}
}

Related

Use session variables in to Hangfire Recurring Job

I have integrated hangfire in to Asp.net web application and trying to use session variables in to Hangfire Recurring Job as like below :
public class Startup
{
public void Configuration(IAppBuilder app)
{
HangfireSyncServices objSync = new HangfireSyncServices();
var options = new DashboardOptions
{
Authorization = new[] { new CustomAuthorizationFilter() }
};
app.UseHangfireDashboard("/hangfire", options);
app.UseHangfireServer();
//Recurring Job
RecurringJob.AddOrUpdate("ADDRESS_SYNC", () => objSync.ADDRESS_SYNC(), Cron.MinuteInterval(30));
}
}
My “HangfireSyncServices” class as below:
public partial class HangfireSyncServices : APIPageClass
{
public void ADDRESS_SYNC()
{
string userName = Convert.ToString(Session[Constants.Sessions.LoggedInUser]).ToUpper();
//Exception throwing on above statement..
//........Rest code.......
}
}
public abstract class APIPageClass : System.Web.UI.Page
{
//common property & methods...
}
but I am getting run time exception as below at the time of getting value in to “userName”:
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the
section in the application configuration.
I have tried to resolve above error using this LINK & other solution also but not able to resolved yet. can anyone help me on this issue.
Thanks in advance,
Hiren
Hangfire jobs don't run in the same context as asp.net, it has it's own thread pool. In fact, Hangfire jobs may even execute on a different server than the one that queued the job if you have multiple servers in your hangfire pool.
Any data that you want to have access to from within the job needs to be passed in as a method parameter. For example:
public partial class HangfireSyncServices //: APIPageClass <- you can't do this..
{
public void ADDRESS_SYNC(string userName)
{
//........Rest code.......
}
}
string userName = Convert.ToString(Session[Constants.Sessions.LoggedInUser]).ToUpper();
RecurringJob.AddOrUpdate("ADDRESS_SYNC", () => objSync.ADDRESS_SYNC(userName), Cron.MinuteInterval(30));
Note that doing the above creates a recurring task that will always execute for the same user, the one that was triggered the web request that created the job.
Next problem: you're trying to create this job in the server startup, so there is no session yet. You only get a session when a web request is in progress. I can't help you with that because I don't have any idea what you're actually trying to do.

JavaFx Turn-based Multiplayer Application with Google Service

Now I am using Gluon plugin and it is very helpful to start working with JavaFXPorts. I have my application ready and I can use it on computers and phones. I tested on phone with system android. Application is working good but only with my server.
I take care of the different resolutions and I think that it is good for now.
I want to have Turn-based Multiplayer Application but I have still big problem with using Google Play Service. Tutorial which show how to use this services for turn-based multiplayer application is written in pure android and use Activity. My question is maybe very simple but If I have my application view from "fxml" how to use it as an tutorial Activity?
I want to do auto-matching for my application and next I want override method takeTurn() to suit it to my application.
For example, how can I change thing like that (code below) to application in JavaFX?
I must use google services from my JavaFX(src/main/java folder) class in addition AndroidPlatformProvider.java and all methods must be in src/android/java folder. I know that I must use PlatformService and PlatformProvider. I did it as in the examples: HelloPlatform and SMSTracker .
I use methods from my interface PlatformProvider but application still crashes. :(
I only use Provider from my code of JavaFX and I don't have android Activity. I don't know how to use these method without Activity or View:
- public void onActivityResult(int request, int response, Intent data)
- public void playTurn(View view)
Can I call from google service methods to methods from my controller for view (fxml).
I don't know how these methods should working with JavaFX.
public class TbmpGameActivity extends Activity {
...
#Override
public void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
...
if (request == RC_SELECT_PLAYERS) {
if (response != Activity.RESULT_OK) {
// user canceled
return;
}
// Get the invitee list.
final ArrayList<String> invitees =
data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);
// Get auto-match criteria.
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
} else {
autoMatchCriteria = null;
}
TurnBasedMatchConfig tbmc = TurnBasedMatchConfig.builder()
.addInvitedPlayers(invitees)
.setAutoMatchCriteria(autoMatchCriteria)
.build();
// Create and start the match.
Games.TurnBasedMultiplayer
.createMatch(mGoogleApiClient, tbmc)
.setResultCallback(new MatchInitiatedCallback());
}
}
}
or something like that:
// Call this method when a player has completed his turn and wants to
// go onto the next player, which may be himself.
public void playTurn(View view) {
// Get the next participant in the game-defined way, possibly round-robin.
String nextParticipantId = getNextParticipantId();
// Get the updated state. In this example, we simply retrieve a
// text string from the view. In your game, there may be more
// complicated state.
mTurnData = mDataView.getText().toString();
// At this point, you might want to show a waiting dialog so that
// the current player does not try to submit turn actions twice.
showSpinner();
// Invoke the next turn. We are converting our data to a byte array.
Games.TurnBasedMultiplayer
.takeTurn(mGoogleApiClient, mMatch.getMatchId(),
mTurnData.getBytes(Charset.forName("UTF-16")),
nextParticipantId)
.setResultCallback(this);
}
Latest version of the jfxmobile plugin (1.0.3) includes recent changes in Dalvik SDK that contains the port of JavaFX 8 to android.
In FXActivity class, it has been added a very convenient method to listen to results of intents: setOnActivityResultHandler().
This means you shouldn't add new activities to your app, and only use FXActivity. You should add an Intent to it, and set a proper result handler to the FXActivity.
Have a look at this recent post at Gluon's site. It explains how to access native services, based on the case of taking a picture with the device's camera, and waiting to get the result of it to resume the app.
Basically, this is what it is required in this case:
public void takePicture() {
// create intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
...
// Add result handler
FXActivity.getInstance().setOnActivityResultHandler((requestCode, resultCode, data) -> {
if (requestCode == TAKE_PICTURE && resultCode == RESULT_OK) {
...
}
});
// launch activity
FXActivity.getInstance().startActivityForResult(intent, TAKE_PICTURE);
}
Try this approach with your app.

ASP.Net Identity 2 Using a custom data access layer like Enterprise Library

I am new to asp.net identity (ver. 2) and am about to start implementing it one of our MVC projects using the Claims based authorization mechanism instead of role based. I having been going through this link where what I understand from what is written is that I need to inherit Microsoft.AspNet.Identity.UserManager and create a CustomUserManager class and override its methods and then implement Microsoft.AspNet.Identity.EntityFramework.IUserStore to be consumed by my CustomUserManager class at the very least. There are other interfaces that I think were designed to be implemented for certain specific conditions like in my case the IUserClaimStore since I want to go with Claims based authorization. The reason mentioned is that I can change the store at a later date incase I want to change my persistence mechanism.
My questions are:
Since I am never going to change the persistence mechanism, is it really required that I implement all those classes and interfaces?
Going through the sample code the most important methods seem to be the following two code blocks:
Identity Creation and save to session (code in DoLogin Method)
// over simplified user object creation
UserPoco userObject= MyDAL.GetUserDatabyLoginDetails(username,password);
//identity created
var identity = CustomImplementationOfCreateIdentity(userObject, DefaultAuthenticationTypes.ApplicationCookie);
//saved to session
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
CheckAccess
public class AppClaimsAuthManager: ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
//bool retVal = context.Principal.HasClaim("MyAction", "SampleResource");
bool retVal = context.Principal.HasClaim(action, resource);
bool baseRetVal= base.CheckAccess(context);
return retVal;
}
}
which is then used in controller methods like so
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "delete", Resource = "SomeResource")]
public ActionResult ClaimsBasedActionMethod()
{
return View();
}
Does it really matter how my user object is created via the CustomManager and CustomUserstore class implementations? Once the user name and password is verified and claims fetched from DB and my userObject created, I should be good to go right? I want this data to be fetched my service layer using enterprise library which I don't want to clog up with all identity framework related references.
Thoughts?

Get names of Online users connected to a Server

I am new to asp.net. I have gone through this link which has shown how to count the online users connected to a server using asp.net. (which is working when I tried)
My question is: What should I change in that code (Global.asax) so that It shows all the names of the connected users instead of counting them.
I created a chat application which stores the name of the connected user in a variable chatUsername in js file as shown below:
js file
var chatUsername = window.prompt("Enter Username:", "");
//
chat.client.addMessage = //Function
//
chat.server.send(chatUsername);
.aspx.cs file
//Using SignalR (I think this doesnt matter)
public class Chat : Hub
{
public void Send(string from)
{
// Call the addMessage method on all clients
Clients.All.addMessage(from);
}
}
You can find my complete code here
EDIT: Please provide a simple example related only to asp.net or signalr (no other technologies like MVC)
Please help.
Edit: following code refers to SignalR v0.5, not the latest 1.0Alpha2, but I believe the reasoning is the same
To do this you need to add several steps to your SignalR connection process, both in the server and in the client:
on the server side:
on application start-up, for example, you can instantiate a static in-memory repository (can be a dictionary of ) that will serve as the user repository to store all currently connected users.
In the hub you need to handle the Disconnect event (when a user disconnects, needs to be removed from the user repository as well) and notify all other clients that this user disconnected
In the hub you need to add two new methods (the names can be whatever you want) that will help client connect to the system and get the list of currently connected users:
GetConnectedUsers() that just returns a collection of connected users
Joined() where the Hub will create a new User, using the info stored in the round-trip state (the username selected by the client) and the SignalR connection ID, and add the newly created user to the in-memory repository.
on the client side:
First you need to instantiate the javascript object that relates to your server-side hub
var chat = $.connection.chat;
chat.username = chatUsername;
Then implements all the functions that will be called by the hub and finally connect to the hub:
// Step 1: Start the connection
// Step 2: Get all currenlty connected users
// Step 3: Join to the chat and notify all the clients (me included) that there is a new user connected
$.connection.hub.start()
.done(function () {
chat.getConnectedUsers()
.done(/*display your contacts*/);
});
}).done(function () {
chat.joined();
});
});
});
If you are asking why we need to add a stage like "chat.joined()" is because in the method on the Hub that is handling the connection event, the round-trip state is not yet available, so the hub cannot retrieve the username chosen by the user.
Anyway I made a blog post to show more in detail how to create a basic SignalR chat web application using Asp.Net MVC, and it is available at:
http://thewayofcode.wordpress.com/2012/07/24/chatr-just-another-chat-application-using-signalr/
In the post you will also find a link to the github repository where the source is published.
I hope this helps.
Valerio
Apparently, you are using Signal-R - so try tracking state of online users (i.e. connected clients) in java-script itself. Use Connected/Disconnected/Reconnected server side events to broadcast to all clients - from documentation:
public class Chat : Hub
{
public override Task OnConnected()
{
return Clients.All.joined(Context.ConnectionId, DateTime.Now.ToString());
}
public override Task OnDisconnected()
{
return Clients.All.leave(Context.ConnectionId, DateTime.Now.ToString());
}
public override Task OnReconnected()
{
return Clients.All.rejoined(Context.ConnectionId, DateTime.Now.ToString());
}
}
A global server side store (for example - a static dictionary) can be used to store state against the connection id - that way, this dictionary can give you users for needed connection ids. For example,
// dis-claimer: untested code - just to give the idea/hint/outline
public class Chat : Hub
{
// change to use Concurrent Dictionary (or do thread-safe access)
static Dictionary<string, User> _users = new Dictionary<string, User>()
// call from client when it goes online
public void Join(string name)
{
var connId = this.Context.ConnectionId;
__users.Add(connId, new User(connId, name));
}
public override Task OnConnected()
{
return Clients.All.joined(_users[Context.ConnectionId], DateTime.Now.ToString());
}
public override Task OnDisconnected()
{
var user = _users[Context.ConnectionId];
_users.Remove(Context.ConnectionId);
return Clients.All.leave(user, DateTime.Now.ToString());
}
public List<User> GetUsers()
{
return _users.Values.ToList()
}
}
I think this should work for you :-
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
Application["OnlineUsers"] = 0;
List<string> list = new List<string>();
}
//First check if it is Authenticated request:-
void Session_Start(object sender, EventArgs e)
{
if(Request.IsAuthenticated)
list.Add(User.Identity.Name);
//your rest of code .......
}
list will return you all the username who are online :-

ASP.net how to long polling with PokeIn?

I want to make a service that notify the user in case there are some new messages sent to him. Thus I want to use some Comet framework that provide the server push ability. So I have looked into PokeIn.
Just wondering a thing. I have checked on the samples that they have on the website. None of them look into the database to retrieve new entries if there are some. But it is just a matter of modification to it I guess.
One of the sample implement this long polling by using a sleep on the server side. So if I use the same approach I can check the database, if there are any new entries, every 5 seconds. However this approach doesn't seem to be much different from when using polling on the client side with javascript.
This part is from a sample. As can be seen they put a sleep there for to update current time for everybody.
static void UpdateClients()
{
while (true)
{
//.. code to check database
if (CometWorker.ActiveClientCount > 0)
{
CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
}
Thread.Sleep(500);
}
}
So I wonder is this how I should implement the message notifier? It seems that the above approach is still going to push a huge load demand on the server side. The message notifier is intend to work same way as the one found Facebook.
You shouldn't implement this way, that sample is only implemented like that because the keep PokeIn related part is clear. You should implement SQL part as mentioned http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
in order to track changes on database.
So, when you have something to send, call one of the PokeIn methods for the client side delivery. I don't know, how much your application is time critical because in addition to reverse ajax, PokeIn's internal websocket feature is very easy to activate and delivers messages to client quite fast.
You can do this with database as #Zuuum said, but I implemented it in a different way.
I'm using ASP.NET MVC with PokeIn and EF in a Windows Azure environment:
I have domain events similar to this approach: Strengthening your domain: Domain Events
When someone invokes an action, that's a Unit of Work
If that UOW succeeds then I raise a domain event (e.g. ChatMessageSent)
I have subscribers for these domain events so they can receive the event and forward the message to the PokeIn listeners
I use this pattern for all my real-time needs on my game site (making moves, actions etc in a game), I don't want to advertise it here, you can find it through me if you want.
I always use this pattern as a duplex communication solution so everybody gets their update via PokeIn, even the user who invoked the action so every client will behave the same. So when someone calls an action it won't return anything except the success signal.
The next examples are won't work because they are only snippets to demonstrate the flow
Here is an action snippet from my code:
[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg)
{
if (ModelState.IsValid)
{
var chatMessage = new ChatMessage
{
ContainerType = msg.ContainerType,
ContainerID = msg.ContainerID,
Message = _xssEncoder.Encode(msg.Message),
User = _profileService.CurrentUser
};
_chatRepository.AddMessage(chatMessage);
OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
}
return Json(Constants.AjaxOk);
}
And the (simplified) EventBroker implementation:
public class UnityEventBroker : EventBroker
{
private readonly IUnityContainer _container;
public UnityEventBroker(IUnityContainer container)
{
_container = container;
}
public override void Send<TPayload>(object sender, TPayload payload)
{
var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
if (subscribers == null) return;
foreach (var subscriber in subscribers)
{
subscriber.Receive(sender, payload);
}
}
}
And the even more simplified subscriber:
public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
public void Receive(object sender, ChatMessageSentPayload payload)
{
var message = payload.Message;
var content = SiteContent.Global;
var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
.Select(c => c.ClientID)
.ToArray();
var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);
var json = PokeIn.JSON.Method("pokein", dto);
CometWorker.SendToClients(clients, json);
}
}

Resources