ASP.NET Core 2.1 Calling Rest API in Quartz.net

Cenk 956 Reputation points
2022-11-16T10:50:49.463+00:00

Hi there,

I have an ASP.NET Core 2.1 web application. The admin gets online game codes from the page below. Selecting the game (Razer Gold Pin), quantity, and email to send those codes.

A Rest API call is made for the purchase. There is a limit for purchasing, a maximum of 200 purchases can be made at once.

At first, there wasn't much to buy so there was no problem. But the demand has increased, when there are 10 thousand, 20 thousand purchases, it is necessary to purchase from this screen for hours. I wonder if can we make a large number of purchases without waiting in front of the screen with scheduling?

260830-yql9f.png

Here is the Javascript in the cshtml:

$("#btn_add").html(  
                            '<span class="spinner-border spinner-border-sm" role="status" id="spinner" aria-hidden="true"></span> Loading...'  
                        );  
                        var selText = $("#validationCustom04").val();  
                        var gameName = $("#validationCustom04 option:selected").text();  
                        var quantity = $("#quantity").val();  
                        var email = $("#email").val();  
                        var price = $("#total").val();  
                        var company = $("#validationCustom05").val();  
  
                        if ($("#total").val() !== '') {  
  
                            price = $("#total").val();  
  
                        }  
  
                        var serviceUrl = '/GameBanks/A101PinAsync?quantity=' + quantity + '&game=' + selText + '&email=' + email + '&prc=' + price + '&gameName=' + gameName + '&company=' + company;  
                        $.ajax({  
                            type: "GET",  
                            url: serviceUrl,  
                            dataType: 'json',  
                            success: function (data) {  
                                //alert(JSON.stringify(data));  
                                ShowResult(data);  
                                $("#spinner").remove();  
                                $("#btn_add").html('Add');  
  
                            }, error: function (xhr, status, error) {  
                                $("#spinner").remove();  
                                $("#btn_add").html('Add');  
  
                                var errorMessage = xhr.responseText;  
  
                                alert('Error - ' + errorMessage);  
                            }  
  
                        });  

Here is the controller method:

[HttpGet]  
public async Task<IActionResult> A101PinAsync(int quantity, string game, string email, int prc, string gameName, string company)  
{  
    var price = 0;  
  
    try  
    {  
        string result = null;  
                  
        var dList = new DemoList();  
  
        if (prc > 0)  
        {  
            price = prc;  
        }  
  
        var games = new Game { Product = game, Quantity = quantity };  
  
        var content = await games.CallGameAsync("Test", "12345", game, quantity, company);  
  
        var deserializedResult = JObject.Parse(content);  
  
        var root = JsonConvert.DeserializeObject<Root>(content);  
  
        if ((string)deserializedResult["coupons"]?[0]?["Serial"] == null)  
        {  
            result = result + gameName + ":" + (string)deserializedResult["Message"] + "\n";  
        }  
        else  
        {  
            foreach (var coupon in root.coupons)  
            {  
                result = result + gameName + "  Serial:" + coupon.Serial + "  Pin:" + coupon.Pin + "\n";  
            }  
        }  
                 
        dList.gameList = result;  
                  
        // NLOG  
        NLogPin(logger, User.Identity.Name, DateTime.Now, result, email);  
                  
        return new JsonResult(dList);  
    }  
    catch (Exception e)  
    {  
        // NLOG  
        NLog(logger2, "OyunPalas " + e.Message, DateTime.UtcNow,0);  
                  
        return StatusCode(500,e.Message);  
    }  
}  

Here is the Web API calling method:

public class Game  
{  
    public string Username { get; set; }  
    public string Password { get; set; }  
    public string Product { get; set; }  
    public int Quantity { get; set; }  
    public string ShopNo { get; set; }  
  
    private static readonly Logger logger2 = LogManager.GetLogger("exceptionFile");  
  
    public async Task<string> CallGameAsync(string username, string password, string product, int quantity, string company)  
    {  
        try  
        {  
            HttpWebRequest request = null;  
              
            request = (HttpWebRequest)WebRequest.Create("http://111.111.111.111:1907//api/v2/web/purchase");  
  
            var svcCredentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password));  
              
            request.Headers.Add("Authorization", "Basic " + svcCredentials);  
            request.Method = "POST";  
            request.KeepAlive = false;  
            request.ContentType = "application/x-www-form-urlencoded";  
  
            var content = new FormUrlEncodedContent(new[]  
            {  
                new KeyValuePair<string, string>("productCode", product),  
                new KeyValuePair<string, string>("quantity", quantity.ToString()),  
                new KeyValuePair<string, string>("shopNo", company),  
                new KeyValuePair<string, string>("safeNo", company),  
                new KeyValuePair<string, string>("cashierNo", company)  
            });  
  
            var urlEncodedString = await content.ReadAsStringAsync();  
  
            using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))  
            {  
                await streamWriter.WriteAsync(urlEncodedString);  
            }  
  
            var httpResponse = (HttpWebResponse) (await request.GetResponseAsync());  
  
            var response = new HttpResponseMessage  
            {  
                StatusCode = httpResponse.StatusCode,  
                Content = new StreamContent(httpResponse.GetResponseStream()),  
            };  
  
            //Read response  
            var htmlResponse = await response.Content.ReadAsStringAsync();  
  
            return htmlResponse;  
        }  
        catch (Exception e)  
        {  
            //NLOG  
            NLog(logger2, "Test" + e.Message);  
            throw;  
        }  
    }  
  
    public void NLog(Logger logger, string user)  
    {  
        var sb = new StringBuilder();  
        sb.AppendLine("Test: " + user);  
        logger.Info(sb.ToString());  
    }  
}  

I have to pass the product (game type) to the job. I read the https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/more-about-jobs.html#jobdatamap documentation but did not fully understand how to use it in my case. And I wonder if I can stop/cancel the job from this page before its end time?

I really appreciate any help you can provide. I'm sorry if the question is too silly as I have no experience with this quartz.net. @XuDong Peng-MSFT

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,165 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,247 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Cenk 956 Reputation points
    2022-12-04T11:39:06.993+00:00

    Is there a way to implement a solution to my problem without using Quartz?

    0 comments No comments

  2. Cenk 956 Reputation points
    2022-12-06T13:47:34.117+00:00

    I thought of a solution like this, but I'm not sure if it's viable.

    • The user will enter which game, how many they want to buy, and their e-mail address on the screen.
    • This data will be saved in a table (BulkRequest) containing this information and the status field in the SQL database. (game: ABC, quantity:20000, status:0)
    • One IHostedService will get the saved data in a schedule which status=0 from the BulkRequest table and the save requests with status information in a new table (GameRequests) in multiples of 100. (game: ABC, quantity:100, status:0)
    • Another IHostedService will get the records in 10 minutes schedule which status=0 from the GameRequests table and make the 3rd party API call. Write a response to another table (GameResponses) and set the status=1 if there is no error.
    • When all requests are completed (status = 1), the status in the BulkRequest table will also be updated to 1.
    • A third IHostedService will check the status of BulkRequest, if status=1 then maybe a fourth service will prepare a file and send the responses to the e-mail.
    0 comments No comments

  3. Bruce (SqlWork.com) 56,026 Reputation points
    2022-12-06T17:25:04.357+00:00

    I would handle each purchase request as standalone.

    loop   
        get next request   
        while more items to purchase    
             purchase from api   
             update database row with successful count (allows restart)   
        end   
        email purchase receipt   
    end   
      
    

    you don't say the rules of the api, but you could run multiple purchase threads, so more than 1 purchase is done at a time. also while bulk purchasing a single item, you could use multiple concurrent requests.