How to utilize re-usable Razor component/view/page (Razor Class Library and ASP.NET Core 6 MVC) through plain html and Javascript?

mehmood tekfirst 771 Reputation points
2022-06-01T12:47:19.067+00:00

Hi,

I am developing a shareable widget by using Razor Class Library and Razor Component.

I want to convert this code in the form of Razor Class Library and then I need to use it in plain html (with JavaScript).

See the following url and answer by ZhiLv-MSFT .

https://learn.microsoft.com/en-us/answers/questions/869660/can-we-use-razorcomponent-in-my-aspnet-mvc-core-6.html?childToView=872715#comment-872715

How can I use it in plain html (with JavaScript) ?

and How can I change the Area Name ?

for example :

207495-image.png

I want to change the name of my feature under Area.
and How can I change the Page Name ?

mv56G.png

This is what I want to do :

please see the full detail now:

I are trying to develop a shareable widget.

I am developing by using razor.view, razor.page and razor.component (project templates are Razor Class Library and ASP.NET Core 6 MVC).

enter image description here

_Imports.razor under RCL Project is as follows:  
  
 @using System.Net.Http    
 @using Microsoft.AspNetCore.Authorization    
 @using Microsoft.AspNetCore.Components.Authorization    
 @using Microsoft.AspNetCore.Components.Forms    
 @using Microsoft.AspNetCore.Components.Routing    
 @using Microsoft.AspNetCore.Components.Web    
 @using Microsoft.JSInterop     
 @using System.IO    
 @using CarRentalWidget.Models.DBEntities.Franchises  
 @using CarRentalWidget.Models.ViewModels.GooogleGeoCodes  

AutoCompleteLocationsComponent.razor is as follows:

@using System.Net.Http  
@using System.Net.Http.Json  
@using System.Threading.Tasks  
@inject HttpClient Http  
@namespace CarRentalWidget.RCL.CarWidgetUI.Pages  
<div>  
                <input  
                    type="text"  
                    id="TxtBxPickUpLoc"  
                    class="postcode tf-form-control"  
                    placeholder="Please Enter Postcode or Town"                                        
                   value="@inputValue"  
                   @onchange="DoChangeLocation"  
                    autoComplete="off"  
                />  
                            @if(!string.IsNullOrWhiteSpace(inputValue))  
                            {  
                                <a className="location" href="#" id="branch-selector" onClick={onClearLocations}></a>  
                            }  
                            else if (string.IsNullOrWhiteSpace(inputValue))  
                            {  
                                <a className="location empty" href="#" id="branch-selector" onClick={onClearLocations}></a>  
                            }  
                   
        </div>  
        <div class="sautocomplete-content-container tk-search-drop-wrapper ac-drop-active">  
            <div class="sautocomplete-content tk-search-drop">  
                <div class="branch-info">                            
                    <ul id="LocationSuggestions" class="suggestions">  
                @if (locationData != null && locationData.Count() > 0)  
                {  
                    @foreach (FranchiseWebInquiry suggestion in locationData!)  
                    {  
                        // Flag the active suggestion with a class  
                        if (index == activeSuggestionIndex)  
                        {  
                            className = "suggestion-active";  
                        }  
                        <li class="@className" key="@index + @suggestion.FranchiseName" onClick="onClick(suggestion)">  
                            <a pickupid="@suggestion.PickupId + @suggestion.FranchisesId"  franchisesid="@suggestion.FranchisesId" subofficeid="@suggestion.SubOfficeId" href="#">  
                                <span class="locName">@suggestion.FranchiseName</span>  
                                <span class="locDetails">@getAddress(suggestion)                                              
                                </span>  
                            </a>  
                        </li>  
                        ++index;  
                    }  
                }  
            </ul>                                
                </div>  
            </div>  
</div>  
    
@code {  
    private string inputValue = "";  
    private string className = "";  
    private int activeSuggestionIndex;  
    private int index = 0;    
    private FranchiseWebInquiry[]? locationData;  
    private bool getError;  
    private bool shouldRender;  
  
    protected override bool ShouldRender() => shouldRender;  
    private GoogleGeocode? currentMapItems;    
  
    private async Task<GoogleGeocode?> loadGoogleGeoCodeData(string postCodeOrTown)  
    {  
        currentMapItems = await Http.GetFromJsonAsync<GoogleGeocode?>  
        ("https://maps.googleapis.com/maps/api/geocode/json?types=geocode&language=en&key=mykey&address=" + postCodeOrTown);  
        return currentMapItems;  
    }  
  
    private async Task getLocationsApi(string postCodeOrTown)  
    {  
        await loadGoogleGeoCodeData(postCodeOrTown);  
        Result? serviceResult = currentMapItems!.Results!.FirstOrDefault();  
        Location? locDetail = serviceResult != null && serviceResult.Geometry != null ? serviceResult.Geometry.Location:null;  
        double providedLattitude = locDetail != null ? locDetail.Lat : 0;  
        double providedLongitude = locDetail != null ? locDetail.Lng : 0;  
        locationData = await Http.GetFromJsonAsync<FranchiseWebInquiry[]?>  
        ("https://localhost:7177/api/CarRental/allfranchises/?postCodeOrAddress=" + postCodeOrTown + "&lattitude=" + providedLattitude + "&longitude=" + providedLongitude);  
    }  
  
    private async void DoChangeLocation(ChangeEventArgs e)  
    {  
        inputValue = e.Value!.ToString();  
        if (inputValue!.Length >= 5)  
        {  
           await getLocationsApi(inputValue);           
        }  
        Console.WriteLine("It is definitely: " + inputValue);  
    }      
  
    private string getAddress(FranchiseWebInquiry suggestion)  
    {  
        //debugger;  
       string localAddress = "";  
  
       if (suggestion != null)  
       {  
          if (!string.IsNullOrWhiteSpace(suggestion.Address1))  
          {  
                localAddress =  suggestion.Address1 + " , ";  
           }                    
  
           if (!string.IsNullOrWhiteSpace(suggestion.Address2))  
           {  
                localAddress += suggestion.Address2 + " , ";  
           }  
  
           if (!string.IsNullOrWhiteSpace(suggestion.Address3))  
           {  
                localAddress += suggestion.Address3 + " , ";  
           }   
  
           if (!string.IsNullOrWhiteSpace(suggestion.Town))  
           {  
                localAddress += suggestion.Town + "- " + (!string.IsNullOrWhiteSpace(suggestion.PostCode) ? "(" + suggestion.PostCode + "), ":"");  
           }  
  
           if (!string.IsNullOrWhiteSpace(suggestion.PrimaryContact))  
           {  
                localAddress += suggestion.PrimaryContact;  
           }             
        }  
  
        return localAddress;    
    }     
}   

and Index.cshtml is as follows:

@page "/car-index"  
@model CarRentalWidget.RCL.CarWidgetUI.Pages.IndexPageModel  
  
<!DOCTYPE html>  
  
<html>  
<head>  
    <meta name="viewport" content="width=device-width" />  
    <title>Car Rental Widget</title>  
</head>  
<body>  
    <div class="widget-wrapper">  
            <div class="main-heading">  
                <h1>                 
                    Test 1  
                </h1>                   
            </div>  
            <div class="widget-slider">  
                <div class="row step-row">  
                    <div class="col-12">  
                        <div class="pickup-location tf-search-group">  
                            <div class="label-location tf-search-label">pick up location</div>  
                            <div id="PickUpLocationControlId" class="input-group-location tf-search-field">                                                                                 
                                <div class="card">     
                                @(await Html.RenderComponentAsync<CarRentalWidget.RCL.CarWidgetUI.Pages.AutoCompleteLocationsComponent>  
                                    (RenderMode.ServerPrerendered/*,new {  Data="I came from Index",style= "badge-danger" }*/))    
                                 </div>                                 
                            </div>                                                          
                        </div>  
                    </div>                    
                </div>  
            </div>  
    </div>  
</body>  
</html>  

Now I just added the reference in my ASP.NET Core 6 MVC project and open the browser and tried this url in the browser.

https://localhost:7177/car-index
Everything is working as expected. No issue till so far.
207611-image.png

Now I am trying to consume this through a plain html (and Javascript/jQuery).

My client end application request is as follows:

<!DOCTYPE html>  
<html>  
<head>  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>  
<script>  
$(document).ready(function(){  
  $("button").click(function(){  
    $.ajax({url: "https://localhost:7177/car-index", success: function(result){  
      $("#CarWidget").html(result);  
    }});  
  });  
});  
</script>  
  
</head>  
<body>  
  
<div id="CarWidget">  
</div>  
  
</body>  
</html>  

See I tried with above script, there is no error code even in Browser Network tab.

Why?

llez9.png

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,199 questions
{count} vote

Accepted answer
  1. Zhi Lv - MSFT 32,016 Reputation points Microsoft Vendor
    2022-06-02T05:40:13.59+00:00

    Hi @mehmood tekfirst ,

    $(document).ready(function(){    
    
         $("button").click(function(){  
          $.ajax({url: "https://localhost:7177/car-index", success: function(result){  
            $("#CarWidget").html(result);  
          }});  
        });  
       });  
    

    See I tried with above script, there is no error code even in Browser Network tab.
    Why?

    Your RCL and the MVC project is correct. The issue relates the CarWidget.html page code. From the above code, we can see that the Ajax method will be executed in the button click event, but there doesn't have a button in the CarWidget.html page. So, it will show blank in the page and there is no request to call the car-index page in the Network tools.

    Try to add a button, and the code like this(remember to change the request URL to yours):

    207707-image.png

    207751-image.png

    Then, from the above screenshot, it seems that you are opening the page via the local browser. If you check the F12 developer tools there might show the CORS error, the issue relates the browser web security.

    If disable the browser web security (Chrome browser, use this command: chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security), the output as below:

    207736-2.gif


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Dillion

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 56,846 Reputation points
    2022-06-01T19:10:07.217+00:00

    you fail to understand how a razor component works. it consists of three parts

    1) a div with an id and a little hookup javascript on the rendered page
    2) a javascript library (blazor.server.js) included on the page used to call the server over signal/r to render the html
    3) a server signal/r endpoint that responds to the javascript library calls to produce the html. a signal/r hub is created for each connected client and it hosts the razor component.

    the html for the component is passed as a razor tree over signal/r. the client javascript library (#2 above) knows how to convert the tree to html.

    it look like you are using Ajax to fetch the hosting page. this may work. you need to add blazor.server.js to the hosting page. also you should set the base href. not sure how well CORS is supported by razor components. I'd start with the page being hosted by https://localhost:7177/

    check the browser debug console for scripting errors.

    I'm not sure how you shutdown the component if you want to load a different dynamic html. see client side Blazor.disconnect();

    1 person found this answer helpful.