Show / Hide Table of Contents

Complete local setup of dev environment

Step 1

Install SqlServer Developer Edition on your machine. This should give you a connection string such as:

Server=localhost;Database=master;Trusted_Connection=True;

Step 2

Use database management tool of your choice and after you connect to the database, run the following queries:

use master;

CREATE DATABASE [sqldb-insight-local];
CREATE DATABASE [sqldb-insight-users-local];

Step 3

Now, the connection strings to the two databases will be:

Server=localhost;Database=sqldb-insight-local;Trusted_Connection=True TrustServerCertificate=True;

Server=localhost;Database=sqldb-insight-users-local;Trusted_Connection=True TrustServerCertificate=True;

and the corresponding commands to set user-secrets will be:

dotnet user-secrets set "ConnectionStrings:Database" "Server=localhost;Database=sqldb-insight-local;Trusted_Connection=True;TrustServerCertificate=True;"

dotnet user-secrets set "ConnectionStrings:UserDatabase" "Server=localhost;Database=sqldb-insight-users-local;Trusted_Connection=True;TrustServerCertificate=True;"

Step 4

Use framework-models and framework-data repositories to setup new data-migrations if needed for sqldb-insight-local db. Utilize auth-server-data repository and any updates/migrations that need to be created for the sqldb-insight-users-local db.

Please make sure the correct connection strings (listed above) are used to create the databases.

Step 5

After you apply the migrations, you should be able to see all the tables created in the appropriate database.

Step 6

Fake data (only supported for non-user database for now) can then be inserted into this local db using the manage-testing-setup project.

Step 7

Make following changes to the study design api:

  1. Make sure the startup allows for anonymous access to the endpoints:
app.UseEndpoints(endpoints =>
{
    if (env.IsDevelopment())
    {
        endpoints.MapControllers().WithMetadata(new AllowAnonymousAttribute()).AllowAnonymous();
    }
    else
        endpoints.MapControllers();
});
  1. Manually add the userid that is associated with the test data (can be obtained from the manage-test-setup project) in the GetSummaries endpoint in the StudiesController.
public async Task<IActionResult> GetSummaries([FromQuery] PaginationFilter paginationFilter)
    {
        var userIdStr = HttpContext.GetUserIdForRequest();
        userIdStr = "0ee85123-e4b7-484f-bc64-08da3aa68e50";
        ...// rest of the code
    }

Deploy study-design-api using the new connection strings.

Step 8

Make the following changes to the study-design-website project

Program.cs

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using WebApp.Client;
using WebApp.Client.Services.Implementations;
using WebApp.Client.Services.Interfaces;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddAntDesign();


//Add an HttpClient service for making authorized calls to the api
builder.Services.AddHttpClient("api", cl =>
{
    cl.BaseAddress = new Uri(builder.Configuration["Addresses:WebAPI"]);
});

builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("api"));

builder.Services.AddSingleton<IHttpService, HttpService>();

builder.Services.AddSingleton<IAssessmentService, AssessmentService>();
builder.Services.AddSingleton<IGroupService, GroupService>();
builder.Services.AddSingleton<IQuestionService, QuestionService>();
builder.Services.AddSingleton<IParticipantService, ParticipantService>();
builder.Services.AddSingleton<IPermissionService, PermissionService>();
builder.Services.AddSingleton<IReportService, ReportService>();
builder.Services.AddSingleton<IStageService, StageService>();
builder.Services.AddSingleton<IStudyService, StudyService>();
builder.Services.AddSingleton<IUserRolesService, UserRolesService>();

await builder.Build().RunAsync();

App.razor


@*<CascadingAuthenticationState>*@
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            @*<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <Authorizing>

                    <Result Icon="loading-outline"
                            Title="Logging you in...">
                    </Result>
                </Authorizing>
            </AuthorizeRouteView>*@
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
@*</CascadingAuthenticationState>*@

<AntContainer />

MainLayout.razor

@inherits LayoutComponentBase
@inject IStudyService StudyService
@inject NavigationManager Navigation
@*@inject AuthenticationStateProvider _authenticationStateProvider*@
@using WebApp.Client.Services.Interfaces;
@using System.Text.Json;
@using WebApp.Client.Pages;
@using WebApp.Client.Pages.SiderNav;


<Layout>
    <Header Class="header">
        <Row Style="height:100%;">
            <GridCol Span="4" Style="display: flex; align-items: center;">
                <img class="insightlogo" src="images/Insight_Icon-transparent.svg" alt="Insight logo" /><span style="color: #c60131; font-size: 28px; font-weight: bold; padding: 0 0 0 0.5rem">Insight</span>
            </GridCol>
            <GridCol Span="18" Style="text-align:center;">

                @if (StudyService.SelectedStudy != null)
                {
                    <span style="font-size: x-large; font-weight: bold;">@StudyService.SelectedStudySummary.Name</span>
                }
            </GridCol>
            @*<GridCol Span="2" Style="text-align: right;">
                <LoginDisplay />
            </GridCol>*@
        </Row>
    </Header>

    @if (hasRunInit)
    {
        <Layout>

            <SiderNav />

            @if (StudyService.SelectedStudy != null)
            {
                <Content>

                    @*@Body*@
                    <WebApp.Client.Pages.Studies.Study/>

                </Content>
            }
            else
            {

                <Content Class="site-layout-background" Style="min-height:100vh;">
                    <Layout Style="padding: 30px 120px 120px; background-color: white;">
                        <PageHeader Class="site-page-header" Style="background-color: lightgray;" Title="@_title" Subtitle="" OnBack="@(()=> { Console.WriteLine("OnBack");})" />
                        <br />
                    </Layout>
                </Content>
            }
        </Layout>

    }
    else
    {
        @Body
    }



</Layout>


@code{


    private string _title = "Please select your study to get started!";

    //[CascadingParameter] protected Task<AuthenticationState> AuthState { get; set; }

    public bool hasRunInit;

    protected override async Task OnInitializedAsync()
    {
        base.OnInitialized();
        Console.WriteLine("MainLayout -> OnInitializedAsync");
        //_authenticationStateProvider.AuthenticationStateChanged += this.OnAuthenticationStateChanged;

        //// If the user is authenticated and reloads the page in the browser, the event won't trigger so we can do the initial load here.
        //var user = (await _authenticationStateProvider.GetAuthenticationStateAsync()).User;
        //Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> IsUserAuthenticated: " + user.Identity.IsAuthenticated);

        //if (user.Identity.IsAuthenticated)
        //{
            hasRunInit = true;
        //    Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> InitUser");
        //}
        //else
        //{
        //    Navigation.NavigateTo(
        //    $"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
        //}
        StudyService.OnChange += StateHasChanged;

        @*var user = (await AuthState).User;
            if (!user.Identity.IsAuthenticated)
            {
                Navigation.NavigateTo(
                    $"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
            }*@
    }

    private async void OnAuthenticationStateChanged(Task<AuthenticationState> task)
    {
        Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnAuthenticationStateChanged -> " + Navigation.Uri);

        var user = (await task).User;
        Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnAuthenticationStateChanged -> IsUserAuthenticated: " + user.Identity.IsAuthenticated);
        if (user.Identity.IsAuthenticated)
        {

            if (Navigation.Uri.Contains("/authentication/login-callback?code") && !hasRunInit)
            {
                Console.WriteLine("Updating MainLayout to show other UI elements.");

                hasRunInit = true;
            }

            @*if (!hasRunInit)
                {
                    hasRunInit = true;

                    Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " CascadingAppStateProvider -> OnInitializedAsync -> InitUser");
                    Console.WriteLine("User authenticated for the first time.");
                }
                else
                {
                    Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> Init has already been triggered!");
                    Console.WriteLine("User authenticated for the second or probably more time");
                }*@
        }
    }
}

<style>
    #components-layout-demo-top-side-2 .logo {
        width: 120px;
        height: 31px;
        color: white;
        margin: 16px 28px 16px 0;
        float: left;
    }

    .site-layout-background {
        background: white;
    }

    .header {
        z-index: 10;
        background-color: white;
        padding: 0 1.5rem;
        box-shadow: 0 2px 8px #f0f1f2;
    }

    .insightlogo {
        width: 50px;
        padding-top: 2px;
        padding-left: 2px;
    }
</style>
Back to top Copyright © mHealth Shared Resource.
Generated by DocFX