मैं वेब नियंत्रक से एमवीसी क्लाइंट को सिग्नलर संदेश कैसे भेजूं?


नमस्ते,

मेरे पास विजुअल स्टूडियो 2017 15.7.5 में Asp.Net Core 2.1, MVC वेब एप्लिकेशन है।

मैं यह पता लगाने की कोशिश कर रहा हूं कि इस प्रकार के लिंक का उपयोग करके एमवीसी व्यू से बुलाए गए नियंत्रक विधि से एमवीसी व्यू.सीएसएचटीएमएल पर एक सिंगल सिग्नलआर स्ट्रिंग टेक्स्ट संदेश कैसे भेजा जाए: @Html.RouteLink(“उत्पाद प्राप्त करें”, ” उत्पाद प्राप्त करें”)।

इसे एक अलग संदर्भ में रखते हुए, मैं अपने नियंत्रक में IHubContext का एक उदाहरण इंजेक्ट करके और इसे कंस्ट्रक्टर में जोड़कर हब के बाहर (सीधे सर्वर से क्लाइंट तक) एक संदेश भेजना चाहता हूं।

मेरा एप्लिकेशन सेटअप इस प्रकार है:

स्टार्टअप.सीएस:

सी#
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using ChinavasionAPI.Data;
using ChinavasionAPI.Hubs;

namespace ChinavasionAPI
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
               // Adds a default in-memory implementation of IDistributedCache.
               services.AddDistributedMemoryCache();

               services.AddSession(options =>
               {
                    // Set a short timeout for easy testing.
                    options.IdleTimeout = TimeSpan.FromSeconds(10);
                    options.Cookie.HttpOnly = true;
               });

               services.AddRouting();

               services.AddSignalR();
               services.AddMvc();

            services.AddDbContext<ChinavasionAPIContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("ChinavasionAPIContext")));

          }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseSession();

            app.UseSignalR(routes =>
            {
               routes.MapHub<ChvHub>("/chvHub");
            });

               app.UseMvc(routes =>
               {
                 routes.MapRoute(
                    name: "token",
                    template: "token",
                    defaults: new { controller = "API", action = "GetAccessToken" });

                 routes.MapRoute(
                    name: "GetCustomers",
                    template: "customers",
                    defaults: new { controller = "Customers", action = "GetCustomers" });

                 routes.MapRoute(
                    name: "GetProducts",
                    template: "products",
                    defaults: new { controller = "Products", action = "GetProducts" });

        }
    }
}

च्वहब:

सी#
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace  ChinavasionAPI.Hubs
{
     public class ChvHub : Hub
     {
          public async Task SendMessage(string user, string message)
          {
               await Clients.All.SendAsync("ReceiveMessage", user, message);
          }
     }
}

चैट.जेएस:

जावास्क्रिप्ट
const connection = new signalR.HubConnectionBuilder()
     .withUrl("/chvHub")
     .build();

connection.on("ReceiveMessage", (user, message) => {
     const msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
     const encodedMsg = user + " says " + msg;
     const li = document.createElement("li");
     li.textContent = encodedMsg;
     document.getElementById("messagesList").appendChild(li);
});

connection.start().catch(err => console.error(err.toString()));

document.getElementById("sendButton").addEventListener("click", event => {
     const user = document.getElementById("userInput").value;
     const message = document.getElementById("messageInput").value;
     connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
     event.preventDefault();
});

उत्पादनियंत्रक.cs:

सी#
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Lakeside.Api.AdapterLibrary;
using ChinavasionAPI.DTOs;
using ChinavasionAPI.Models;
using ChinavasionAPI.Models.CAPIViewModels;
using ChinavasionAPI.Data;
using ChinavasionAPI.Hubs;
using Microsoft.AspNetCore.SignalR;

namespace ChinavasionAPI.Controllers
{
    public class ProductsController : Controller
    {
          private readonly ChinavasionAPIContext _context;
          private readonly IHubContext<ChvHub> _hubContext;

          public ProductsController(ChinavasionAPIContext context, IHubContext<ChvHub> hubcontext)
          {
               _context = context;
               _hubContext = hubcontext;
          }

          public async Task<IActionResult> GetProducts()
          {
               var model = new AccessModel();
               model.UserAccessModel = _context.UserAccessModels.Single(a => a.ID == 1);

               var accessToken = (model.UserAccessModel.AccessToken ?? TempData["accessToken"]).ToString();
               var serverUrl = (model.UserAccessModel.ServerUrl ?? TempData["serverUrl"]).ToString();

               var nopApiClient = new ApiClient(accessToken, serverUrl);
               MultipleProductModel multipleProductModel = new MultipleProductModel();
               List<Category> categories = new List<Category>();

               string jsonUrl = $"/api/products?limit=75&fields=id,sku,name,images,categories";
               object productsData = nopApiClient.Get(jsonUrl);

               var productsRootObject = JsonConvert.DeserializeObject<ProductsRootObject>(productsData.ToString());             
               var products = productsRootObject.Products.Where(
                    product => !string.IsNullOrEmpty(product.Name));

               multipleProductModel.MProductsApi = productsRootObject.Products;

               int? setupID = 1;
               if (setupID == null)
               {
                    return NotFound();
               }

               var setup = await _context.Setups.SingleOrDefaultAsync(m => m.ID == setupID);
               if (setup == null)
               {
                    return NotFound();
               }

               serverUrl = setup.ServerUrl;
               string serverKey = setup.Key;
               string queryCall = "api/getProductDetails.php";
               string parameterName = "model_code";
               multipleProductModel.MProducts.Clear();
               var productsService = new Service.ProductService();

               foreach(ProductApi nopProduct in products)
               {
                    Product chvproduct = (await productsService.GetProductBySkuAPIAsync(serverUrl, serverKey, queryCall, parameterName, nopProduct.Sku));
                    if (chvproduct == null)
                    {
                         multipleProductModel.MProducts.Add(new Product { product_id = 0, model_code = "Not on file" });
                    }
                    else
                    {
                         multipleProductModel.MProducts.Add(chvproduct);
                    }
                    await this._hubContext.Clients.All.SendAsync("ReceiveMessage", "NewMessage", "AnotherNewMessage");
               }

               return View("~/Views/API/Products.cshtml", multipleProductModel);
          }

AccessToken.cshtml:

एचटीएमएल
@model ChinavasionAPI.Models.AccessModel
@using Microsoft.AspNetCore.Http.Extensions

@{
     ViewData["Title"] = "Access Token";
}

@section Scripts {
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
     <script src="~/lib/signalr/signalr.js"></script>
     <script src="~/js/chat.js"></script>
}
     <div>
          <h2>Access Data</h2>
          @using (Html.BeginRouteForm("Submit", FormMethod.Post))
          {
               <table>
                    <tr>
                         <td>
                              <label for="serverUrl">Server url: </label>
                         </td>
                         <td>
                              <input name="serverUrl" type="text" id="serverUrl" value="@Model.UserAccessModel.ServerUrl" style="width:400px" />
                         </td>
                    </tr>
                    <tr>
                         <td>
                              <label for="clientId">Client Id: </label>
                         </td>
                         <td>
                              <input name="clientId" type="text" id="clientId" value="@Model.UserAccessModel.ClientId" style="width:400px" />
                         </td>
                    </tr>
                    <tr>
                         <td>
                              <label for="clientSecret">Client Secret: </label>
                         </td>
                         <td>
                              <input name="clientSecret" type="text" id="clientSecret" value="@Model.UserAccessModel.ClientSecret" style="width:400px" />
                         </td>
                    </tr>
                    <tr>
                         <td>
                              <label for="redirectUrl">Redirect Url: </label>
                         </td>
                         <td>
                              <input name="redirectUrl" type="text" id="redirectUrl" readonly="readonly" value="@Model.UserAccessModel.RedirectUrl" style="width:400px" />
                         </td>
                    </tr>
                    <tr>
                         <td></td>
                         <td>
                              <br />
                              <input type="submit" value="Get Access Token" />
                              <button type="button" id="refresh-token-button">Refresh Access Token</button>
                         </td>
                    </tr>
               </table>
          }
     </div>

     <div class="container">
          <div class="row">
               <div class="col-6"> </div>
               <div class="col-6">
                    <ul id="messagesList"></ul>
               </div>
          </div>
     </div>

     @Html.RouteLink("Get Customers", "GetCustomers")
     @Html.RouteLink("Get Products", "GetProducts")

जब मैं यहां से उत्पन्न लिंक पर क्लिक करता हूं: @Html.RouteLink(‘उत्पाद प्राप्त करें’, ‘उत्पाद प्राप्त करें’)यह रिटर्न व्यू (“~/Views/API/Products.cshtml”, multipleProductModel); से प्रदर्शित होने से पहले “GetProducts” में सब कुछ संसाधित करता है, लेकिन यह AccessToken.cshtml व्यू स्क्रीन पर कभी भी कोई संदेश प्रदर्शित नहीं करता है।

जब मैं फ़ायरफ़ॉक्स में डेवलपर टूल का उपयोग करता हूं, तो कंसोल कंसोल में सिग्नलआर वेब सॉकेट कनेक्शन दिखाता है (वेबसॉकेट ws://localhost:64370/chvHub?id=QeZ8xRJSFHuzzQIZ72X2dg से जुड़ा है), लेकिन तब जब मैं यहां से उत्पन्न लिंक पर क्लिक करता हूं: @ Html.RouteLink(‘उत्पाद प्राप्त करें’, ‘उत्पाद प्राप्त करें’), यह दिखाता है कि यह डिस्कनेक्ट हो गया है (कनेक्शन डिस्कनेक्ट हो गया है)।

साथ ही, जब मैं विजुअल स्टूडियो डीबगर का उपयोग करता हूं और इसे GetProducts विधि में रोकता हूं, तो _hubContext में कोई कनेक्शन नहीं होता है।

किसी कारण से, जब नियंत्रण उत्पाद नियंत्रक के पास जाता है, तो सिग्नलआर कनेक्शन खो जाता है।

एक सिग्नलआर संदेश को एक दृश्य में प्रदर्शित करने में सहायता के लिए कोई भी व्यक्ति जो भी सहायता प्रदान कर सकता है, उसकी कृतज्ञतापूर्वक सराहना की जाएगी।

धन्यवाद,
टोनी

मैंने क्या प्रयास किया है:

मैंने इस पंक्ति को स्टार्टअप.सीएस में कॉन्फिगरसर्विसेज विधि में जोड़ा है:

services.AddSignalR();

मैंने इन पंक्तियों को स्टार्टअप.सीएस में कॉन्फिगर विधि में जोड़ा है:

सी#
app.UseSignalR(routes =>
            {
               routes.MapHub<ChvHub>("/chvHub");
            });

मैंने IHubContext का एक उदाहरण इस प्रकार इंजेक्ट करने के लिए अपने नियंत्रक को कॉन्फ़िगर किया है:

सी#
public class ProductsController : Controller
    {
          private readonly ChinavasionAPIContext _context;
          private readonly IHubContext<ChvHub> _hubContext;
          public ProductsController(ChinavasionAPIContext context, IHubContext<ChvHub> hubcontext)
          {
               _context = context;
               _hubContext = hubcontext;
          }

क्लाइंट को संदेश भेजने के लिए नियंत्रक में यह पंक्ति जोड़ी गई:

सी#
await this._hubContext.Clients.All.SendAsync("ReceiveMessage", "NewMessage", "AnotherNewMessage");

नुगेट पैकेज मैनेजर कंसोल में मैंने ये कमांड चलाए:

एनपीएम इनिट-वाई
npm @aspnet/signalr इंस्टॉल करें

मैंने Nuget पैकेज प्रबंधित करें के माध्यम से स्थापित किया: Microsoft.AspNetCore.SignalR नवीनतम स्थिर 1.0.2।

समाधान 1

मैं यह नहीं कह सकता कि मैंने इसका पता लगा लिया है, लेकिन मैंने विशेष रूप से इससे प्रेरित विभिन्न कोडिंग रणनीतियों का परीक्षण करके इसे काम में लाने में कामयाबी हासिल की है लेख[^] डिनो एस्पोसिटो द्वारा।

मैंने “GetProducts” के लिए एक बटन बनाया और AccessToken.cshtml फ़ाइल में निचले “div” को इस तरह संशोधित किया:

जावास्क्रिप्ट
<div class="container">
     <div class="row">
          <div class="col-6"</div>
          <div class="col-6">
               <ul id="messagesList"></ul>
          </div>
     </div>
     <form asp-controller="Products" asp-action="GetProducts">
          <div class="form-group">
               <br />
               <input type="submit" id="get-products-button" value="Get Products" class="btn btn-default" onclick="startTask()" />
          </div>
     </form>
</div>

<script>
     function startTask() {
          $.get("/products/getproducts/");
     }
</script>

<script>
     document.getElementById("get-products-button").addEventListener("click", event => {
          event.preventDefault();
     });
</script>

मैंने यह देखने के लिए कि बटन सक्रिय हो रहा है या नहीं, डिबगिंग सहायता के रूप में निचली स्क्रिप्ट जोड़ी।

उपरोक्त कोड के किसी भी भाग के बिना, क्लाइंट को संदेश काम नहीं करते हैं। मैं इसे समझा नहीं सकता, मैं बस इतना जानता हूं कि अगर मैं इसका कोई हिस्सा हटा दूं, तो यह क्लाइंट को संदेश प्रदर्शित नहीं करता है।

ग्राहक को संदेश प्रदर्शित होते हैं, लेकिन इस सफलता की एक कीमत चुकानी पड़ती है। जब GetProducts विधि इस पंक्ति पर आती है:

सी#
return View("~/Views/API/Products.cshtml", multipleProductModel);

यह Product.cshtml दृश्य स्क्रीन प्रदर्शित नहीं करता है। यह कोई त्रुटि नहीं देता, यह बस प्रदर्शित नहीं होता।

GetProducts विधि उसी तरह से प्रक्रिया करती है जैसे उसे करनी चाहिए, लेकिन यह उस दृश्य को प्रदर्शित नहीं करेगी।

मैं इसकी सराहना करूंगा यदि कोई मुझे बता सके कि वह दृश्य क्यों प्रदर्शित नहीं होगा।

धन्यवाद,
टोनी

コメント

タイトルとURLをコピーしました