简体   繁体   English

ASP.NET Core 2.1 在一个schedule中调用Rest API

[英]ASP.NET Core 2.1 Calling Rest API in a schedule

I have this ASP.NET Core 2.1 web application.我有这个 ASP.NET Core 2.1 web 应用程序。 The admin gets online game codes from the page below.管理员从下面的页面获取在线游戏代码。 Selecting the game (Razer Gold Pin), quantity and email to send those codes.选择游戏(Razer Gold Pin)、数量和 email 发送这些代码。

A Rest API call is made for the purchase.购买电话 Rest API。 There is a limit for purchasing, a maximum of 200 purchases can be made at one time.购买次数有限制,一次最多可购买200次。

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.但是需求量增加了,当有1万、2万的采购量时,就需要在这个屏幕上采购几个小时。 I wonder can we make a large number of purchases without waiting in front of the screen with scheduling?我想知道我们是否可以在不在屏幕前等待调度的情况下进行大量购买?

在此处输入图像描述

Here is the the Javascript in the cshtml:这是 cshtml 中的 Javascript:

$("#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:这是 controller 方法:

[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:下面是Web API的调用方法:

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 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 not fully understand how to use in my case.我阅读了https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/more-about-jobs.html#jobdatamap文档,但不完全了解如何在我的案例中使用。 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 scheduling.如果这个问题太愚蠢,我很抱歉,因为我没有这种安排的经验。

Edit:编辑:

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.此数据将保存在包含此信息和 SQL 数据库中状态字段的表 (BulkRequest) 中。 (game: ABC, quantity:20000, status:0) (游戏:ABC,数量:20000,状态: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)一个 IHostedService 将从 BulkRequest 表中获取状态 = 0 的计划中的已保存数据,并在新表 (GameRequests) 中以 100 的倍数获取带有状态信息的保存请求。(游戏:ABC,数量:100,状态: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.另一个 IHostedService 将在 10 分钟内从 GameRequests 表中获取 status=0 的记录,并进行第 3 方 API 调用。 Write a response to another table (GameResponses) and set the status=1 if there is no error.将响应写入另一个表(GameResponses),如果没有错误则设置状态=1。

  • When all requests are completed (status = 1), the status in the BulkRequest table will also be updated to 1.当所有请求完成后(status = 1),BulkRequest表中的status也会更新为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.第三个 IHostedService 将检查 BulkRequest 的状态,如果 status=1 那么第四个服务可能会准备一个文件并将响应发送到电子邮件。

I do suggest reviewing message queuing tools such RabbitMQ. With this architecture you will do all the jobs using messaging protocols with no need for "scheduling" and any "x minutes schedule" s would be ommited.我确实建议查看消息队列工具,例如 RabbitMQ。使用此架构,您将使用消息传递协议完成所有工作,而无需“调度”,并且将省略任何“x 分钟调度”。 Also it is more stable and error handling could be done using best practice standards.它也更稳定,并且可以使用最佳实践标准来处理错误。 More important, it is scalable and you can have multiple hostedServices even on different servers process items in queue:更重要的是,它是可扩展的,你甚至可以在不同的服务器上拥有多个 hostedServices 队列中的进程项目:

  • When request is registered send a message (publish) to the queue.注册请求后,向队列发送消息(发布)。
  • The hostedService1 receives the item and process it (consume). hostedService1 接收项目并处理它(消费)。 Multiple services may subscribe to process requests.多个服务可以订阅处理请求。
  • The hostedService1 may do all the job it self or even dispatch some parts to other services using the same method hostedService1 可以自己完成所有工作,甚至可以使用相同的方法将某些部分分派给其他服务

The solution you proposed is doing the same job with an ad-hoc process.您提出的解决方案是通过临时流程完成相同的工作。 In fact you are reinventing the wheel.事实上,你正在重新发明轮子。 Hope it helps.希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM