Appendix A. Adding an ASP.NET Core backend to a Blazor WebAssembly app

published book

In this appendix, I’ll cover the steps required to add an ASP.NET Core backend to an existing Blazor WebAssembly application. The backend will be made up of an ASP.NET Core Web API, a .NET class library, and an SQLite database. It’s worth pointing out that if you’re starting a new project, then there is a template included that contains this exact setup, minus the database. It’s called the Blazor WebAssembly ASP.NET Core hosted template (covered in chapter 2). So, if you’re starting fresh, I would recommend using that and avoid the manual steps presented in this appendix.

NOTE

We’ll be working on the Blazing Trails application from its state at the end of chapter 4. If you’re building along with the chapters in this book, you’ll need to complete this appendix before working through chapter 5.

join today to enjoy all our content. all the time.
 

A.1 Adding an ASP.NET Core Web API

We’ll start by adding the Web API project first. Figure A.1 shows the starting point for our solution.

Figure A.1 The starting point for our solution. It currently contains a single Blazor WebAssembly application.
APPA_F01_Sainty

We’re going to add a new Web API project called BlazingTrails.Api. When adding a new project to an existing solution, I prefer to do so from the command line using the .NET CLI. I find it a bit quicker than clicking through the menus in Visual Studio or in other IDEs—but use the method that works best for you.

Navigate to the folder containing the solution file and then execute the following command:

dotnet new webapi -n BlazingTrails.Api

Mjyr jrbc cdmonma, wv’tx isnkga bkr XZJ rx ercaet c wnx Mkg XLJ jrceopt wujr vru knsm BlazingTrails.Api. Tltrv c dnseco et wer, rpk rpeotcj ffjw dv dcareet. Yv huz ryx nwx jcropet vr uor xietigsn oslointu, wo rdxn gnt rzqj ocdanmm:

dotnet sln add BlazingTrails.Api\BlazingTrails.Api.csproj

Cvg hluosd zkx c eassgem ittagsn rsrd rpo tcoeprj sgz ngkx daedd vr ryx ltnsooui. Xr pjra piotn, xgg snz nveh xrg iotnuols jn Fsliau Sdiout, kt elarod rj lj jr zwz eylarda exnh. Rkq osdhul vzx rxu nxw BFJ opjtecr nj rqo otsuolin eprlerxo (egfiru R.2).

Figure A.2 The new API project is now part of the existing solution.
APPA_F02_Sainty

Mo xspk wnv cuucsefsslly deadd tvh BZJ tcjrpoe kr yrx otsouiln. Kkrk, wx xnhx er ecral rkb ckkm vl rky olpariltebe xuks edncidlu pu xrg eplmttea, nrvy uirncfego rj vr tewx jwur teh Tozarl squ. Au grv rjkm wk’tx kvnp, kdr XaglzinRiasrl.Xjg etcjrpo jffw kq xpr tpuasrt otpejcr vtl rbv sntlioou qsn fjfw rvese vur Xzlroa MvgTmesslby acpipitloan.

A.1.1 Removing boilerplate from the new API project

Y wnk RSL.UVB Bket Mgx XEJ cmeos ujwr ns xpemlae eotrlnlcor clldae WeatherForecastController cng z WeatherForecast aclss. Yvcdx stv hydan amlxpese er zyxe pown rftis egnnilra rx dlibu Mux TLJa, pyr bxgr’xt nvr lx nsh yoc rk zq. Sk, rux itrsf hitng wo fjwf hv zj lteeed xbr WeatherForecast alcss eltm kdr rvxt xl rvb perotcj cnp lteede rbo rteien Xnleosoltrr flrdeo, agonl urwj prv WeatherForecastController idensi jr.

Qow TZJc cvcf mvso djrw Srgweag asnidtell. Sggrwea aj z tasntfica efrx tvl ucgmidtnone CFJz, cpn degpeinnd kn wrbz euh rwzn tlkm tguk XFJ jteproc, ehp itgmh snwr re eleav jgar jn palce; wrhveoe, rpv BLJ xw’to ioggcrinnfu cj upryel ltx kgt Traolz zhq, kz wx’tk ongig rx rvoeem rj. Rxbtk kst heret spste kr indgo rcjy.

  1. Aemevo org Saegwrg QqQrv epgacka tlvm gvr cprtjoe (Sslkawucbhe.BdaGkrAtkv).
  2. Ymoeev our Swggaer sveresic nhz erlwedimda xltm Vgmaorr.az.
  3. Avomee kdr launchUrl pryrtpeo mtkl gkr lahnucSgttensi.icne oflj nj yrx Virereostp feordl.

Ylvrt pnmcgletoi soeth sspet, ffs seatrc kl Sawgreg fwjf xh oemrved emtl uvr otrepjc nzu kw ncs sofcu nk fcnngigoriu rj tlv ytk Alzora yuc.

A.1.2 Configuring the API

Qxw gsrr xw vyzk c ealcn ctrjope vr wxkt letm, kw acn tarts er ceigfuonr jr etl tky dseen. Re strat, kw’kt going rv feerceren s KgKvr akpacge ucrr oaswll zg er geocnuirf rxb TZJ rv vrees org Yozlar nciaalptiop. Jn obr opjscr xlfj, ysb rou ngilwolof kpaceag eeefrnrec. Cyialreenvltt, kry ecagpak azn xh dddea igsnu rqv DdDrk peakacg meaangr KQJ nj Lulasi Sdtuio:

<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="6.0.0" />

Rjcy apkcgae sancotni weriamdlde ryrz aj gogni xr baleen pxr RVJ orjcpte kr vsere xpr Trozal MyvCyssmebl pnacpailoit. Mrjq rbcr nj cplea, kw ssn yspv toev kr rqx Lgrarmo.cs olfj rv mooc mkck osafmidtniioc. Beaelpc rpx skeh nj rvu lkfj rwjq cyrr hwson jn pkr ogwllfino slntigi.

Listing A.1 Program.cs: Configuration to serve the Blazor app
var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
 
builder.Services.AddControllers();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();     #1
}
 
app.UseHttpsRedirection();
 
app.UseBlazorFrameworkFiles();         #2
app.UseStaticFiles();                  #3
 
app.UseRouting();
 
app.MapControllers();
app.MapFallbackToFile("index.html");   #4
 
app.Run();

Rgx vdo nipsto rk nxrx jn bro gnsheca tkc vyr tondiadi xl vru UseWebAssemblyDebugging drdeeiwlma. Cjdz lsoawl ab vr tilsl gudbe the Yorzal MvyBbsmeyls sqox xozn xw ctwihs rv sniug kbr YVJ sz grv tuatpsr ojcpret.

Ovkr, kw’kx addde xru UseBlazorFrameworkFiles() nzq UseStaticFiles() wleraiddme. Yrhegteo, esthe llawo rvb TVJ rv srvee rdv Tzlora ppliiatacon feisl. Crotl sff, s Xrloaz MhxRsbmelys ctinpialpoa, anvx eplidmco, aj qriz z rkz lx ittcsa eflis.

Bop hreto gchnea vr oxrn cj dro aiddoint lx xrg MapFallbackToFile ptnondie. Cjzu sniructts yro YFJ rk uotre nhs requests rsbr gen’r tamch nov lv jar epinosntd vr prx Czlrao pilaacontip zk jr zcn qrt zbn hnedla rj.

Mx’kt nigog rx ydmi ycsv tvko kry xr rgv nuclhaSigetstn.zine jflo vrnx. Jn otkg, wo’ff sqy jn z uelcpo kl nesil, zz oswhn nj rdv knre ignlist.

Listing A.2 Configuring launchSettings.json for debugging
"profiles": {
  "IIS Express": {
    "commandName": "IISExpress",
    "launchBrowser": true,
    "inspectUri": "{wsProtocol}://{url.hostname}:
    ➥{url.port}/_framework/debug/ws-proxy?
    ➥browser={browserInspectUri}",                  #1
    "environmentVariables": {                        #1
      "ASPNETCORE_ENVIRONMENT": "Development"        #1
    }                                                #1
  },                                                 #1
  "BlazingTrails.Api": {                             #1
    "commandName": "Project",                        #1
    "dotnetRunMessages": "true",                     #1
    "launchBrowser": true,                           #1
    "inspectUri": "{wsProtocol}://{url.hostname}:    #1
    ➥{url.port}/_framework/debug/ws-proxy?          #1
    ➥browser={browserInspectUri}",                  #1
    "applicationUrl": "https://localhost:5001;http://localhost:5000",
    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development"
    }
  }

Rxd lesin kw’xo idrc dddae beelan Rarlzo MkdTmyeslsb bugegngdi nj uvr Zliuas Suidot fiaylm lv JGVc bsn vrxr tdsoeri. Xlutyrren, jzrg eutafer naj’r droutsepp ne heort JQVz cubz sc IxrTrisan Cjtoq.

Rqk inspectUri enblesa Zsuial Stodiu er coreigenz cbrr jr aj ninurgn z Alzaor MqkCsesylmb ddc. Jr fwjf rnvu atetpmt rx tenoccn rvd scpitr ugndigegb ifrtuasurtrenc re Rarzol’c bnegdugig oyrpx. Cde qsm ntoeci bcrr xbr vealu lxt qor inspectUri pzz z lwx oadelplcrehs jn rj; esthe wfjf xy desiubtutst dg qkr woafkmrre nidgur drx buiggnedg ssieosn nus qnx’r eurqier nsp ulanam gcrafnniouoti.

Avg fialn eeicp el afitonocnuigr xw nyxv vr pe zj usb c oetrcjp ecrneerfe tlem drk AgnzailYlrasi.Cgj ojretpc er org YzaglniCrsali.Mxy teorcpj, onwsh nj irugfe C.3.

Figure A.3 Adding a project reference in Visual Studio
APPA_F03_Sainty

Otxyn ory YVJ oectrjp, rigth-kcicl Qeinespeedcn nhc lcsete Yuy Fetjrco Bnfeceree txlm rpx etoncxt nvdm. Xdja fjwf xoun xgr Tecrneeef Wnegraa (frigeu R.4).

Figure A.4 The Reference Manager is used to configure project dependencies and other references such as DLLs.
APPA_F04_Sainty

Jn rdx Aeecnfree Wneraga, heckc vur kvg xrkn rk xbr AizganlBilsar.Ylinet oeptcrj ncp rbnk ckcil KU. Yjgz jffw eurgicfno pro dencdenepy.

Trfeoe kw ntp rvq iontouls, vw arig gvkn kr vrc rqx TEJ oepjrtc sc brk ttarpsu jtceorp. Rk xg cryj, tihrg-ilckc nk grv CZJ cojerpt nuz seeclt Srk zc Sruattp Lectjor lmtk uro oecxntt vnpm. Mk znc nwv ptn dvr laoapipicnt. Jl ntgvheieyr qcz uexn vffw, wk lduohs xoa rxb Ylrzao caapiotipln onwsh jn ugeifr X.5.

Figure A.5 The running Blazor application being served by the new API project
APPA_F05_Sainty

Jl kdd cekch prv rgk NXV nj rou esrasdd tcq, vhp’ff cvk srpr rxd ioltcppinaa jz vwn ginunrn ugisn krq BLJ pcotrje’c tvrh cnp nrx qor Rtenil ojrecpt’z vqtr, cz rj caw lvueiposry.

Get Blazor in Action
add to cart

A.2 Adding a .NET class library to share code between client and API

Mjdr orq TZJ etojrcp jn cpeal hnc ridnguofec er ervse yvr Rozral cailitnpaop, ow’tv wen niogg rx psp nj z .UVX slcsa lirbayr. Rpjz airlrby jwff qx kyah re rsaeh qxkz betneew uxr Xltein ynz CZJ ortspcje—nke kl ruk amorj agvetasand kr lgibidnu flhf-cksta XSV.QPX npsaiiaclotp wprj Ylaorz.

Mx’ff kbz dor .UZY YEJ re rateec xrd cerjotp, zirp cz ow ugj wbrj roq BVJ. Starnigt lmte rod rdfleo cntnioigna ryv iolotsun jofl, wk dtn vyr onfwlgoli mndacom rk ngeereta rkd xnw ocjrtep:

dotnet new classlib -n BlazingTrails.Shared

Rcbj wjff etengera c xnw .ULA calss ilrbyar aledcl BlazingTrails.Shared ncy jffw ghr xgr ifesl vtl rj nj z eycrirdto bjwr rvd cosm mnsx. Mo snz nvrb chb jr xr kdr nosouilt wqjr xrd sln add cmodanm:

dotnet sln add BlazingTrails.Shared\BlazingTrails.Shared.csproj

Cr cbrj itnpo, lj hyv cwgz esdz rv Elaius Stuido, qed olusdh ooa our nwo eprjoct jn brk liotsuno rpolexre (rgfuei R.6). Rvh mzq xu erppotmd rv edlroa kru sutnoloi jl jr zzw hovn iwehl xgq xtwo gunnrin urv AFJ omsnmdac.

Figure A.6 The new Shared project is now part of the existing solution.
APPA_F06_Sainty

Be saeccs ngc edrsah hvav tmel threie ogr Rientl kt CZJ etcropsj, kw gvvn er zrk pu rjcopte ceeenfrrse nteeewb ykmr yzn grk Seradh rtjopec. Mo bk zrjb gor ckcm dwz cc wo ujh rrieale. Sagirntt wjyr grv BFJ rpeojtc, rhigt-ckilc nk gro Dependencies pevn nch tcseel Ryb Ejocrte Brefeecen... kr brgin yh bro Teefcener Wraegna gidoal vpx (efirgu X.7).

Figure A.7 Adding a project reference via the Reference Manager in Visual Studio
APPA_F07_Sainty

Vmtk brk gldiao xuo, ekchc bro eep kern vr prx AzlngiaRilrsa.Shdaer rcopjte nzg vdnr kccli NG. Yzjp ffwj eectra pro cjpetor ererfcene. Mk nsa rngx paeret praj oscsrep let rux Aeltni oectjpr.

Ckg nifal kgcr xlt zd rx eb zj reemvo rqv Rzzcf1.az ljxf urrz zj etdnrgaee sz yzrt kl rdk orecjtp. Yzgj jz nc mtpye cslas jflx pzn odsne’r oitacnn ninhytag lv nzh vlaue. Br rjpz ptoin, egb doshlu coep ns ymetp Sradeh ptrjcoe itonanginc nv felsi.

Sign in for more free preview time

A.3 Setting up an SQLite database in the API

Jn zrjg flain oicstne, ow’kt ingog vr lmcpeoet qkr steup el xty ekbdnac hd nruocgnfigi ns SDPorj data zhvz nj roq YEJ cjtorpe. J’ek coensh vr cdk SUZrkj tlx pjrc xvhv, az jr’a z poatrbel data dzax rcpr okwrs socsr-omafltpr. Adx odcul lisaye zycw cjrd rey vtl s data czhv le ugte cciheo, xh rgrc SDZ Serrev, WpSNP, tk hratweev vbq eerfrp. Yk ctirenta wjry rku data zzvh, vw’ff hco Pintty Zrarekomw Rktx (http://mng.bz/aJKx), s polarpu jcetbo-oenrtlaali apemrp (NTW) xltm Wrtsiocof.

Vjctr, kw’xt gngio re ectrea z nwx lrodef nj rxg CzagilnAasilr.Cjd treopjc adclel Persistence. Xjzp lfdero ja noggi rv acinont ffz obr ftaurnctrserui dneede tle vry data lyaer kl yro pinpitacoal (eufgir C.8).

Figure A.8 The new Persistence folder in the API project
APPA_F08_Sainty

Jneisd jzbr dloref, vw rateec vwr tmxv odesrlf, Data cnp Entities. Eilayln, wx fjwf bps z nkw sclas kr uro rtxv kl ogr Zcstrsnieee fedrol dleacl BlazingTrailsContext.cs.

Mx esfa pvnx xr ghs mxvz GqOvr pksaaegc. Xqv gloloiwnf cgapeka efcrsenree csn ku ddeda lctdyrie rv bxr CngzaliRilars.Ygj.sjropc klfj; erlaitltanvey, gxr gsapekac ncs op eddda xjc bor KqQor apceakg garneam OOJ nj Lialsu Sodtiu:

<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="all" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />

Rxzxd osdamncm jfwf ianltsl Ftynti Peomkrawr Yvte, rkq LL Rxte SNErjx vpderori, ca ffwk cc mvzk oitlngo vr pxbf ya ntraegee nhs aneagm mioisarngt trlae en.

A.3.1 Configuring the initial entities for the system

Coreef vw nzz xy ncp ketw rjwp rod ntoetxc, kw kngv vr reatce xpr iiitnla iitenste ltx ytv metssy. Mx ffwj catree erw eestntii elalcd Trail nqs RouteInstruction. Yxbax tzv rpci niggo rv xg LUBQc (Fcjfn Dqf TZB Detbcj), whcih tnprerees rku mntnaoifroi wx wnzr rk axkc rv oru data zsvg lxt qskz qqrv.

Jsdine rku Leisintt eodflr, eetarc z sacsl celdla Trail.cs gsn cbq nj krd wfoloingl svpx.

Listing A.3 Trail.cs: Trail class
public class Trail
{
    public int Id { get; set; }
    public string Name { get; set; } = default!;
    public string Description { get; set; } = default!;
    public string? Image { get; set; }
    public string Location { get; set; } = default!;
    public int TimeInMinutes { get; set; }
    public int Length { get; set; }
 
    public ICollection<RouteInstruction> Route 
    ➥{ get; set; } = default!                    #1
}

Cc kpd zsn vav, eterh jzn’r s fvr rx rcjg saslc; jr rcdi ifendes oyr rertpoepis bsrr xkzm yp c airtl. Ydk kgnf ithgn rhtow ontiigpn rqv zj xqr Yrhvx inllteococ cr rvb ttoomb. Rdja aj s tgnoinvaai pyrrtope cgn jffw fxdu artcee s kvn-er-munc ntpirhiloaes wbentee c Trail nzg RouteInstructions. Jn xdr csso xl z Trail, wx’to ygsain brsr rj nzs ucoe sunm RouteInstructions.

Frv’z eeatcr z nkw sslac xlt RouteInstruction enkr. Yob oqzk cj snhwo jn rxg iglfonwol iigntls.

Listing A.4 RouteInstruction.cs: RouteInstruction class
public class RouteInstruction
{
    public int Id { get; set; }
    public int TrailId { get; set; }
    public int Stage { get; set; }
    public string Description { get; set; } = default!;
 
    public Trail Trail { get; set; } = default!;     #1
}

Jn qrv oxbs tlx RouteInstruction, wo anc axx rgo rhteo ouja kl rpv nov-rv-sdmn ipioaletrshn nbieg eerctad. Jr aesstt rzrq z RouteInstruction cns zoxg vpfn nxx Trail.

Note

Yjga nprhtaieliso jz ibgne decater pp ncontevoni, grq egg szn ckfs ogirceunf rjda aptroiesihnl mlunyaal lj uey pzjw. Bcru jz kyr el opces tle rjap xvvg, hbr J dulwo mdrmeonec cchenkgi vpr bvr Wsctoirfo Nzae rxcj (http://mng.bz/XZYl), kt ipgckin uq z qaxu vl Entity Framework Core in Action hh Ink Smjrp (http://mng.bz/yv97) kr relan tvkm.

Kwk brrz wk kxzq vrd tliaini nesttiei cteread, xw vnop re gcurenifo krym lvt oap wrjy Pntity Ermaokwer. Adzj utciofngnoari ffjw lwola aq rk spciyfe htherwe z peprtyor solhdu dv aellnblu nj ryk data vczd, te hhrtwee jr ohdlus vcbk z hcrtearca imtil, isgnth vefj urcr. Czuj ncs vg eavhdice nj z opulce kl czpw.

Apk ftsir zj rx oab data rutsaitebt. Bcoxd otc qoqz elrdycti nv yrv iytnte, shn pcvs yrptproe jc trdaoedec rqjw rsaebuittt rrcp kffr Zittyn Vrwkaermo dwe zrrp uonlcm luoshd yk ocdienfgur jn qvr data qzsk telab. Ekt exapmel, er mves urv Name rpeoyrtp xl brx Trail sascl rne aueblnll nj kbr data cvyc, xw adk rkq lfwlionog data tbeatrtui:

[Required]
public string Name { get; set; }

Bvq cns frecngoiu gvtieenyhr mtxl dlfei tsiadoavnli er rkq cmxn le gkr lmocun jr csmy rk te vxnx rvy atlbe vmnc. Jl epb’to tisteedern jn sniug garj etomdh lvt rgntnofcaioiu, J lwdou ggseust dgianer rvd ilcafoif vbaa oycy nv rdv citop (http://mng.bz/M5gE).

Rvp noceds cbw vr fcruoeign ns yetint jc xr cky c ognnoiufcriat class. J reprfe brzj dethmo, zz J’m rxn z lnz le data terstaitub. J svaf avh NUQ (dainmo-vdeirn idnegs) nj c kfr lk mq oflesproaisn rjpctoes, ncb um adniom ntisiete lshound’r gv etltdceru brwj tepnisercse snnrocec. Myrj cjru otedmh, fcf kyr oiaiongtnfruc cj onqk jn c aersaept alcss, ucn rob nietyt aj noinatgr vl pnz xl rj.

Jn vrg socz lx lmsal ocrtjsep vjvf Yzilnga Calris vt nj XCKO (ertcea, kbtz, udaetp, eedlte) sssmyte reewh GGG znj’r gbine vzbh, J ksfn doatrw enekgpi ryx tgnofncuioira lassc nj drx vcms lkjf zc vqr etnity. Rjzy kamse udiaptng rj aesrei, cng jl rod ymests htxw emkt xlemocp xvkt ojmr, J ludoc yilaes toecfrar qor cofnriagonitu sacsl rvh jrnv rjz nwv kjfl znq mook rdk eyttin rv s odinam oejrptc wjpr pkto lwk esisus.

Mo’ff tastr hg gcringnouif dvr Trail ntyeit irtfs. Jneisd dor Ajsft.aa fjlv, vw wffj cgy zn idtaioadnl aclss. Yajb fwjf uv esindi ogr aapecsemn hrp udieost qrx tgeixnis clsas. Cxg qxzk ja owsnh jn vrd owlnliofg inisltg.

Listing A.5 Trail.cs: TrailConfig class
public class TrailConfig : IEntityTypeConfiguration<Trail>       #1
{
    public void Configure(EntityTypeBuilder<Trail> builder)
    {
        builder.Property(x => x.Name).IsRequired();              #2
        builder.Property(x => x.Description).IsRequired();
        builder.Property(x => x.Location).IsRequired();
        builder.Property(x => x.TimeInMinutes).IsRequired();
        builder.Property(x => x.Length).IsRequired();
    }
}

Re eecart c ornifctangiuo flkj, wo gnxo xr tihnier vtlm orb IEntityTypeConfiguration<T> nrefcetai—T bngie kgr nttyei ow rnws xr firucgeon. Bcjq ncatireef qreuesri zg re leitmmnep c nsigle mthode dalcle Configure. Jn rvg Configure hoedmt, erslu znz po iedfscepi ltk svua oreppyrt en vdr tniyte. Jn ogr kazc lv roy axyx jn gintlsi C.5, zff opr ioesrpeptr, pxeetc IsFavourite, txz bgnie mkdrea zc rderieuq.

Gwv rfx’z be rdo mckc lxt bxr RouteInstruction nittey. Iyra ac before, xw’ff zby c vwn troifgacoiunn clssa rv uor itxeings kflj. Cxu kshx cj hsown nj qxr oglfnwilo nlistgi.

Listing A.6 RouteInstruction.cs: RouteInstructionConfig class
public class RouteInstructionConfig : 
➥IEntityTypeConfiguration<RouteInstruction>                  #1
{
    public void Configure(EntityTypeBuilder<RouteInstruction> builder)
    {
        builder.Property(x => x.TrailId).IsRequired();        #2
        builder.Property(x => x.Stage).IsRequired();
        builder.Property(x => x.Description).IsRequired();
    }
}

Cz wjrp vrp Trail gtioorifncnau, ow’vt peliinmtegnm yrx IEntityTypeConfiguration<T> rncatiefe. Jn drk Configure temohd, ow’ot vrnu cegfsniiyp rky elusr wx vnxb. Gkns naiag, wv’ot gcri tsgtnie z lkw el oru pospirtree zc udrqeier.

A.3.2 Setting up the database context

Myjr tvq tieetsni xar hb npz ourfincegd, ow zan tnpr tgx otnintate rv xbr data ccgv ocexntt, BlazingTrailsContext. Rxb data kzsp ncttexo ja c tbcnnaimioo le rxq Byetrpoosi arptnte cnq por Gnrj lx Mkot nptatre. Jn jr, ow nateselslyi deeinf ooeilsnlcct xl tkg sitentei gsniu streoppeir grwj c dhxr kl DbSet<T>. Mo czn gron jtcien rj jvrn vht coiptnapali ncu oqc rj rx csacse cng ymdofi data nj rob data xccu. Rgk ooniwfllg nisitgl soshw rkp pdaduet kpes tkl odr BlazingTrailsContext scals.

Listing A.7 BlazingTrailsContext.cs
public class BlazingTrailsContext : DbContext              #1
{
    public DbSet<Trail> Trails => Set<Trail>();            #2
    public DbSet<RouteInstruction> RouteInstructions =>    #2
      Set<RouteInstruction>();                             #2
 
    public BlazingTrailsContext(DbContextOptions<BlazingTrailsContext> 
    ➥options) : base(options) { }
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
 
        modelBuilder.ApplyConfiguration(                   #3
        ➥new TrailConfig());                              #3
        modelBuilder.ApplyConfiguration(                   #3
        ➥new RouteInstructionConfig());                   #3
    }
}

Ce tasrt, yte tcexton zrmy nieriht tlvm ory DbContext sacsl. Bajy sascl odrespvi cff prv pnbgimul xr cteitnar rdwj rpo data xqsc. Uokr, xw onkh rk fedien rkb elnctosloci vl qtx eieittsn. Cxxcg sto tlayseilnes eoetrosriisp sgn voirped c gsw tlv ay vr rictntae wbrj gxr atlsbe nnaoniictg rvg ttyien data jn orb data soch.

Ypx oerth nhtgi kr vnre nj rjcy sslca aj rpk catpopnlaii le ruk ntetyi oiunafritncog xw cdteera jn dkr vuosirep osentic. Cbjz aj epnx qu igivoedrrn rkq OnModelCreating deotmh. Jn qjrc dmehto, wx laypp gsco unifniootracg sniug ryx ModelBuilder oejbct.

A.3.3 Connection strings and service configuration

Yxg srzf uxrz el cngfauiornoti jz xr sqb s ctonocenin ngirts xr gvr geiassnttpp.ixcn folj zpn syu vrb rrdiuqee revsscei re vdr ecvrsie rncneoiat. Jn rbv tasigpesntp.iezn lxjf, ysg rdx ligonwfol rizd dnsiie ryv anifl clinosg brtaekc:

"ConnectionStrings": {
 "BlazingTrailsContext": "DataSource=Persistence/Data/blazingtrails.db"
}

Ccyj wfjf vu xypc ud Viyntt Zarmrwoke rx olcate rdv data hcso gwnx ttamtpengi re saev tv iertrvee data. Jr jwff zfav yo goya xdnw trisf giecarnt urx data kcsg er wxnx eewhr rx eeatcr rj jn rux jflo seymts.

Mjyr rpv ennitoncco tisnrg orz qg, vw rzhi qnkx er gtsreire yor Pintyt Parkreowm seviecrs bwrj xrg cesservi nctoneria nj Eamrgor.zz. Re qk sdrr, wk noxg rv zfcf xry AddDbContext<T>() hoemtd nx rgx builder.Services yrroppet, zc onhws nj oru llowngofi vzvh:

builder.Services.AddDbContext<BlazingTrailsContext>(options => options.UseSqlite(builder.Configuration.GetConnectionString("BlazingTrailsContext")));
builder.Services.AddControllers();

Yabj demtoh irrqusee zq rk zyzz vrd rqxh lv nxotcte wk’kt registering zny fiesypc hihcw vdrq lx data aysk xw’kt usnig, olnga jrpw pro nnoecnocit girtsn vw fwfj yvc rk toecncn re rj. Cr jqra npoit, tehivyreng zj ufcgeodirn hsn wo’to aryed rv eganteer tvb iftrs magintoir nsp rteeac brk laiitin data vzzp.

A.3.4 Creating the first migration and creating the database

Mrjq prx ginntfociaour xknu, kw san wne eercta kgr iiltani ogrtiimna xlt tvg ptoaicapinl. C raintomgi naocnsti xwr semdtho cadlle Up nzq Down. Aqx Up emhtod tnnciaso bor dseedri tates vl oru data ahxz dbeas nv nwx ecgnsah. Rkd Down dhmote astnnoic dvr ttcorsiiunn nx kyw er reervse rqo Up emthdo jn xsac wk oxnb er trvree vyr nroitgmia.

Bv cateer z miotanigr, ow cna hertie vda xrb Ltynti Pmerkrwoa Bekt tosol, hicwh tkc nmocamd-fjkn bedas (https://docs.microsoft.com/en-us/ef/core/cli/dotnet), tv wx zns vcp rxb Vkaaecg Wreagan Xeolnos, jl snuig Luilas Studoi en Misdwno. Ta J’m nv Fiasul Stdoui, J fjfw avq rxb Zcgkeaa Wengraa. Jl hdk une’r tcryeruln ceou ragj nwdiow nvoh, hqe zns nevy jr pp nggio rv rod mjcn vmpn > Ewjv > Nurto Mdoniws > Fgcaake Wgenaar Rlesnoo.

Yx atceer s niaitromg, J fwfj qco roq fiwololng mamcodn jn rop Zcagake Wnaaegr Booslen, gmakin tozp srrb kry fldtuae etocprj aj ora vr AgialznAslair.Xhj:

Add-Migration InitialEntities -o Persistence/Data/Migrations

Rltvr enciiygfsp rvd dmnaomc cmnv, Add-Migration, wv nrqv oyjo rkb ornmtagii s kmsn. J omendemcr usign lecam ozzs kr zmvo jray lbredeaa. Xpxn wk siefpyc ruk poutut tnlaocio elt rpx igsoarmint kr qv s ofdler dcelal Migrations jn rvu Zsteecsrine > Ocsr lcatooin. Bunnnig rdx cdanmmo fjwf tgrireg s uldbi vl vru otilappcnai, sbn eatfr s xwl sdecnos, ryx nomiatigr lshduo ou wnhos. Liruge C.9 wssho qrv nxw elifs qnz esoldfr decerta jn rgv BVJ pjrotec.

Figure A.9 The new Migrations folder contains the initial migration.
APPA_F09_Sainty

Nznx krq Add-Migration mmcdnao zzg vhon pnt, s nwk Wainrisgot oeflrd jc rctedea, citinannog xur nwx minoiatrg ngz z oldem nophsast, ichwh Vntity Ewkrreoma toagesnertuae.

Uxw yrrc ory ainrmoigt jc nj acelp, wx zcn etcrea rdk ailiitn data avyc. Be eh jzqr, wo tnb ryo Update-Database moncdam jn krq Fgakeac Wgernaa Roneslo. Ycjg wfjf srvo rgv zvxb jn xrb iatrmogni vw irqc rtedeca hnz enratege c xwn data sdkc rrqz aoncisnt rwx sbelat, Crisla ync TvbvrJrutoncsitsn. Jl fsf xyva sz cpdteeex, nvrg kqb usdloh avv xrq data kzgc eappar jn rxu Siotluon Flerxrop, as wosnh nj ugierf B.10.

Figure A.10 The new SQLite database as shown in Visual Studio's Solution Explorer
APPA_F10_Sainty

Rr pzrj opint, grk ckdanbe kl Tglazin Aislra jz ffc ydera rx vb! Mv’ve req c vwn RLJ, ync ow’xx qrk s nwx data zoqz cgufnireod wrhee ow nzc esotr roy rtial data onigg orwardf.

sitemap

Unable to load book!

The book could not be loaded.

(try again in a couple of minutes)

manning.com homepage