<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kasey Wahl</title>
    <description>The latest articles on Forem by Kasey Wahl (@piaomu).</description>
    <link>https://forem.com/piaomu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F620865%2Fa19e83e3-f565-4c29-aed1-030fea84d1c8.jpeg</url>
      <title>Forem: Kasey Wahl</title>
      <link>https://forem.com/piaomu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/piaomu"/>
    <language>en</language>
    <item>
      <title>LINQ Queries | Dev [Over]simplified</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Wed, 23 Jun 2021 17:22:13 +0000</pubDate>
      <link>https://forem.com/piaomu/linq-queries-dev-over-simplified-jda</link>
      <guid>https://forem.com/piaomu/linq-queries-dev-over-simplified-jda</guid>
      <description>&lt;p&gt;So you're eating at the dinner table when this alien come's up to you like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UxpjZsF0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gu44x0age81bbu2yivv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UxpjZsF0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gu44x0age81bbu2yivv.png" alt="Glootie"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you're like, "Sure."&lt;/p&gt;

&lt;p&gt;So you decide you're going to code up a blog in C# because you need a place to store all of your ideas.&lt;/p&gt;

&lt;p&gt;So you code up &lt;a href="http://www.dear-coder.com/KaseysPosts/SEOFriendly/c-sharp-classes-objects-and-class-members-explained-by-dan-harmons-community"&gt;classes&lt;/a&gt; in the shape of Posts, Blogs, and Comments--everything you need for a basic blog. &lt;/p&gt;

&lt;p&gt;You find some cute HTML blog template, slap it into your Solution, and you're ready to publish.&lt;/p&gt;

&lt;p&gt;And then it occurs to you:&lt;/p&gt;

&lt;p&gt;You don't have anywhere to store your data--the &lt;em&gt;strings&lt;/em&gt; and &lt;em&gt;ints&lt;/em&gt; and &lt;em&gt;DateTimes&lt;/em&gt; that, for now, you're storing in that big ol' head of yours.&lt;/p&gt;

&lt;p&gt;You're alien friend's like, "Hey, I've got an idea. Why don't you store all that in a &lt;em&gt;database&lt;/em&gt;?"&lt;/p&gt;

&lt;p&gt;You're like, "That's pretty chill."&lt;/p&gt;

&lt;p&gt;So you download a bunch of NuGet packages, wire your database to your solution, set your first data migration, and you're set!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k2sKbNnH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fye8e14efe0qgmq3v2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k2sKbNnH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fye8e14efe0qgmq3v2i.png" alt="migration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or so you thought.&lt;/p&gt;

&lt;p&gt;You've actually just encountered another roadblock.&lt;/p&gt;

&lt;p&gt;Even though you're wired to a database that stores all of the data tables you need, you don't speak SQL, the &lt;em&gt;language&lt;/em&gt; that databases understand.&lt;/p&gt;

&lt;p&gt;Your application consists of two star-crossed lovers who's love letters are lost at sea.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_mnAq2ho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n5rz911qeactbtpnflb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_mnAq2ho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n5rz911qeactbtpnflb.jpg" alt="star-crossed lovers"&gt;&lt;/a&gt;&lt;br&gt;
If only there was something...someone who could take a request in C# and translate it into usable SQL code that the database could understand!&lt;/p&gt;

&lt;p&gt;The dark hour is upon you. You've lost sleep. It shows in the sagging, fleshy bags under your eyes.&lt;/p&gt;

&lt;p&gt;It seems all hope is lost. You're about to raise the white flag of defeat.&lt;/p&gt;

&lt;p&gt;That is...&lt;/p&gt;

&lt;p&gt;Until LINQ, our hero arrives:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E-qmLxRo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1ljv73h19iwfctldaue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E-qmLxRo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1ljv73h19iwfctldaue.png" alt="LINQ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LINQ, or &lt;em&gt;Language Integrated Query&lt;/em&gt;, takes your C# request and translates it into something that your SQL-speaking database knows what to do with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oIGuAe9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju6hhbr0gih1m5wq615v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oIGuAe9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju6hhbr0gih1m5wq615v.png" alt="LINQ Query"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wanna store some blog data? Use LINQ to tell that dataBaby where to put it and .SaveChangesAsync().&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UMJvo8v---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38hpinw1wosh6ffk1pdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UMJvo8v---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38hpinw1wosh6ffk1pdx.png" alt="Data from M'lady"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wanna spin up a Post to display in your application? Tell LINQ to hit the Post table. Don't forget to .Include() all of the comments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nuylF289--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbn2wa67rj4bppsq17oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nuylF289--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbn2wa67rj4bppsq17oh.png" alt="LINQ saves the data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short, LINQ is our hero that allows us C# devs to query a database (among other things) and make that data sing, baby:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/C_6raHHDLEA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h3&gt;
  
  
  Want to learn more about LINQ?
&lt;/h3&gt;

&lt;p&gt;I hope you enjoyed this entry in my Dev [Over]Simplified series, dear Coder. If you want a more technical explanation on LINQ, check out the resources below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/introduction-to-linq-queries"&gt;Introduction to LINQ Queries&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.tutorialsteacher.com/linq/linq-query-syntax"&gt;LINQ Tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>entityframework</category>
    </item>
    <item>
      <title>10 Perspectives I Changed During the Pandemic (and how they led me to tech)</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Thu, 17 Jun 2021 15:16:18 +0000</pubDate>
      <link>https://forem.com/piaomu/10-perspectives-i-changed-during-the-pandemic-and-how-they-led-me-to-tech-bg6</link>
      <guid>https://forem.com/piaomu/10-perspectives-i-changed-during-the-pandemic-and-how-they-led-me-to-tech-bg6</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;Today's letter is a little different.&lt;/p&gt;

&lt;p&gt;Most of you don't know me or my background. I'm going to write about me a little, because it's unavoidable when I explain what drove me to tech.&lt;/p&gt;

&lt;p&gt;I didn't go to school for Computer Science. I come from a background in English Composition and Education. In the "before-times," I wrote the International English curriculum for a boarding school in Beijing, China.&lt;/p&gt;

&lt;p&gt;The short version of the story: I was on holiday outside of China visiting family and friends when the pandemic hit. My return flight to Beijing got cancelled. I've been living out of a suitcase and a backpack for the last ~17 months.&lt;/p&gt;

&lt;p&gt;It's been hard. Like, really hard. &lt;/p&gt;

&lt;p&gt;My career evaporated before my eyes. I've (vainly) tried to get back to my belongings and life in China.&lt;/p&gt;

&lt;p&gt;But at a point, I had to make peace with loss, take inventory of my surroundings, and decide what I was going to do.&lt;/p&gt;

&lt;p&gt;I looked around me and found a backpack full of books, a suitcase full of winter clothes, a small bag of toiletries...&lt;/p&gt;

&lt;p&gt;...and my laptop computer.&lt;/p&gt;

&lt;p&gt;I asked myself: "What can I do with this?"&lt;/p&gt;

&lt;p&gt;Here are ten answers to that question, more or less, given that situation (and how they led me to tech).&lt;/p&gt;

&lt;h2&gt;
  
  
  1. I never store belongings in closets, on clothes hangers, or in drawers anymore - my bags are always packed
&lt;/h2&gt;

&lt;p&gt;I'm learning what "home" means in a visceral way, and I'm still evaluating what the term means.&lt;/p&gt;

&lt;p&gt;I miss it: taking the elevator to the third floor of my Beijing apartment and fussing with the sticky lock under the dim, flickering hallway light in front of my door.&lt;/p&gt;

&lt;p&gt;I miss it because once I was inside, I was home. I was safe. I could change into comfy clothes and sprawl out on the couch. I miss the days of leaving evening dishes until the morning, because they were my dishes in my space. I miss turning the lock on my door and only opening it if I wanted.&lt;/p&gt;

&lt;p&gt;Since January 2020, I've had to pack up my suitcase 10 different times to go somewhere else. Being constantly on the move is mentally and emotionally taxing, but when I reflect on what I've gained and what I've lost, I see the virtue of frugality.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. I only buy things in travel sizes and varieties
&lt;/h2&gt;

&lt;p&gt;A foldable toothbrush, a set of sortable clothing bags, a first-aid kit, miniature toiletries tucked neatly into a red zippered canvas: these are the items that fit into my suitcase. They're all I can fit; they're all I can afford; they're all I need.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. I give away my paperback books when I finish reading them
&lt;/h2&gt;

&lt;p&gt;There's a collection of books on my desk in my office in Beijing. Most of them are academic, littered with sticky notes and marked with highlighters. They cover pedagogy, approaching English from a non-native learner's perspective, and addressing one's own biases as a native speaker.&lt;/p&gt;

&lt;p&gt;There's a collection of novels on the bookshelf in my bedroom too -- great books: Toole's &lt;em&gt;A Confederacy of Dunces&lt;/em&gt;, Vonnegut's &lt;em&gt;Slaughterhouse Five&lt;/em&gt;, Twain's &lt;em&gt;A Connecticut Yankee in King Arthur's Court&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's a shame they're collecting dust.&lt;/p&gt;

&lt;p&gt;I still love to read.&lt;/p&gt;

&lt;p&gt;But when I buy a book these days, I give it away when I'm finished because great ideas are meant to be shared, and even if I wanted, I couldn't bring the damn book with me anyway.&lt;/p&gt;

&lt;p&gt;If it's &lt;em&gt;really&lt;/em&gt; good, I'll buy a digital copy later.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. I don't like receiving gifts anymore
&lt;/h2&gt;

&lt;p&gt;The week before I left Beijing, a Chinese colleague gave me a fantastic Christmas gift. It's a graphic novel, written in Mandarin, in both Traditional and Simplified characters, about Buddhist thought. It's titled "放下是舍更是得", which means "&lt;em&gt;Letting Go is Gaining More&lt;/em&gt;." I brought it with me to read on the plane out of Beijing, not knowing I was letting go of everything I was leaving behind.&lt;/p&gt;

&lt;p&gt;Gift-giving is an integral part of Chinese culture, and I've learned a lot about what giving meaningful gifts means.&lt;/p&gt;

&lt;p&gt;If that book is the last gift I ever receive, my heart is full.&lt;/p&gt;

&lt;p&gt;I still read it with a kind of desperation, in part because I'm still learning the language in which it's written, and partly because, through pandemic times, I'm drawn to it's lessons like lightning to a rod.&lt;/p&gt;

&lt;p&gt;The more I learn, the more I code, the more I give, and the more I let go of things I can't control, the more content I am.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GZwfXinS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v4ulf5y5v55rrkbnuvz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GZwfXinS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v4ulf5y5v55rrkbnuvz.jpg" alt="Letting Go is Gaining More"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Letting Go is Gaining More&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. I talk less, listen more, and take notes on everything
&lt;/h2&gt;

&lt;p&gt;One of my greatest fears when I started teaching was when my students would expose a gap in my knowledge or understanding of my own field. I used to feel like I &lt;em&gt;needed&lt;/em&gt; to answer every question if I was worth anything as a teacher or as a writer. I'd get so desperate to have an answer, I'd start prattling off an ill-formed explanation before the entire question had even left my student's mouth.&lt;/p&gt;

&lt;p&gt;The result was always hopeless frustration.&lt;/p&gt;

&lt;p&gt;The more I taught, the more I was able to accept that I don't always need to have the answer to questions immediately. Sometimes it's better to fully listen to the question.&lt;/p&gt;

&lt;p&gt;I mean, carefully, intently listen to the question: it's structure, it's wording, the rationale behind the question.&lt;/p&gt;

&lt;p&gt;And sometimes its okay to admit you don't know the answer, write a note, and come back with a well-researched answer later.&lt;/p&gt;

&lt;p&gt;Over time, "unanswerable questions" became my favorite part of teaching. People are so much more interesting when they come to you from a place of curiosity than when they pretend to know everything, and when I listened to a student's question, I'd learn so much about them.&lt;/p&gt;

&lt;p&gt;When I could return a thoughtful answer later, we all learned.&lt;/p&gt;

&lt;p&gt;Everyone had questions when Covid-19 broke out.&lt;/p&gt;

&lt;p&gt;I shouldn't have been shocked that so many people leaped at the opportunity to insert quick, ill-formed answers, because I've been that person and I know why they feel like they need to do that.&lt;/p&gt;

&lt;p&gt;I've since taken to coding, and I don't pretend to have the answers, but I always have a notebook and pen nearby.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. I've been learning how to learn, therefore I'm more content in the moment
&lt;/h2&gt;

&lt;p&gt;When I was in college, I used to think "learning" meant reading complicated texts and asking unreasonably big questions about those texts.&lt;/p&gt;

&lt;p&gt;When I started learning Mandarin and teaching English, I realized learning is more like repeated blunt-force trauma to the head.&lt;/p&gt;

&lt;p&gt;More than anything, it's about repetition and consistency. It's about starting small, building up, and returning to the small principles for review.&lt;/p&gt;

&lt;p&gt;Sometimes you'll easily master a word or phrase or grammar rule. Sometimes they just won't stick.&lt;/p&gt;

&lt;p&gt;But if you're willing to keep making mistakes and learning from them, no matter what you're studying, it will make sense eventually.&lt;/p&gt;

&lt;p&gt;In my post-pandemic life, I've found that learning to code flexes those same "brain muscles". I don't get frustrated as easily because I pick appropriate goals that I can replicate, and I make sure I code every day for as long as the day allows.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. I'm more patient
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"We're not accepting applicants from outside of China at this time."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I can't tell you the number of times a great job interview has concluded with those words in the past ten months.&lt;/p&gt;

&lt;p&gt;I don't know how I would have survived had I not given myself the permission to be patient with the process of rejection since the world closed down. &lt;/p&gt;

&lt;p&gt;But that patience was permission-giving as well. I had permission to learn new things: more Mandarin, art, and now web development. It's an enduring kind of patience that I bring into the workplace, because I trust that I'll learn what I need to learn in the time I need to learn it.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. I read people better--their desires and sources of joy and pain
&lt;/h2&gt;

&lt;p&gt;In the first few months of the pandemic, I was stranded on an island off the coast of Thailand (a long story for another time). &lt;/p&gt;

&lt;p&gt;I met an old Austrian man there named Werner.&lt;/p&gt;

&lt;p&gt;When ferry services got suspended, a group of Brits, an Italian, and myself were discussing what the suspension might mean for travelers and transportation of goods. The conversation was a bit unnerving, so I tried to calm things down by suggesting things would be fine.&lt;/p&gt;

&lt;p&gt;Werner interrupted me.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I was three years old when the Nazis raided my family's factory and stripped it beam-from-beam to make weapons,"&lt;/em&gt; he cried. &lt;em&gt;"Things are fine now, but what will people do when there's not enough?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I shut up and listened.&lt;/p&gt;

&lt;p&gt;He told me his story about fleeing Austria for South Africa after the Nazi incident, where he later became a businessman with a reputation for driving around in his flower-painted Volkswagon Beetle.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"They called me the last hippie in Pretoria,"&lt;/em&gt; he said.&lt;/p&gt;

&lt;p&gt;Thanks for the title of my first novel, Werner.&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;I don't understand the world now,"&lt;/em&gt; he continued. &lt;em&gt;"You have your smart phones and smart watches and social media. You put up all these pictures, and I think you have such beautiful lives until I meet you. I don't understand why young people lie to each other on the internet. This world wasn't built for me."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When he finished talking, I gave him a hug and went back to my room to take notes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JVrLaSuB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26z4ajahz9csy48sh3k7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JVrLaSuB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26z4ajahz9csy48sh3k7.jpg" alt="The Last Hippie in Pretoria"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Last Hippie in Pretoria&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. I tell people I love them more often
&lt;/h2&gt;

&lt;p&gt;Three months ago, I was walking down Phillips Avenue--one of the main streets in my hometown--on a Saturday evening. A homeless man bundled in scarves stumbled towards me.&lt;/p&gt;

&lt;p&gt;I did something impulsive. Going against everything my parents ever taught me about strangers, I hugged him tightly for a few seconds and said, "I love you, man."&lt;/p&gt;

&lt;p&gt;He didn't say anything--just nodded for a moment.&lt;/p&gt;

&lt;p&gt;He was drunk.&lt;/p&gt;

&lt;p&gt;But so was I.&lt;/p&gt;

&lt;p&gt;He was homeless.&lt;/p&gt;

&lt;p&gt;And so was I.&lt;/p&gt;

&lt;p&gt;I make a point to find reasons to love people these days.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. I want to make things for people: permanent things in virtual spaces
&lt;/h2&gt;

&lt;p&gt;During the Spring semester of 2020, I taught 14 kids in Beijing from my computer over a spotty wi-fi connection at a youth hostel in Thailand.&lt;/p&gt;

&lt;p&gt;Though I'd written their curriculum in conjunction with TOEFL preparation materials and high school graded novels, all of our learning materials were locked inside our school in Beijing while they were locked down at home and I was stuck in Thailand.&lt;/p&gt;

&lt;p&gt;I still taught three hours of class everyday. I spent nearly every waking hour of time outside of class preparing materials for the next day's lessons--reading materials, quizzes, review texts, instructional videos, animated shorts. I did all of it.&lt;/p&gt;

&lt;p&gt;I remember constantly thinking &lt;em&gt;if only I had more time to prepare.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A funny thing happens in a time of desperation.&lt;/p&gt;

&lt;p&gt;You rise to the occasion.&lt;/p&gt;

&lt;p&gt;I won't pretend like I optimized every day.&lt;/p&gt;

&lt;p&gt;But I was present, and I showed up with materials for my students to learn.&lt;/p&gt;

&lt;p&gt;And I learned too: &lt;/p&gt;

&lt;p&gt;I learned how to use rudimentary animation software to help explain complex rhetorical ideas.&lt;/p&gt;

&lt;p&gt;I learned how to integrate ClassDojo into our routine to manage my classroom, accept homework from students, present learning materials to them, and all while largely circumventing &lt;a href="https://en.wikipedia.org/wiki/Great_Firewall"&gt;the Great Firewall of China&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I remember signing off our Zoom meeting on the last day of class and weeping into my hands.&lt;/p&gt;

&lt;p&gt;Though I look back on the experience now through a healthy lens of what I learned, I still remember feeling like nothing we had done during the semester was enough. None of it was planned. How could it have been? &lt;/p&gt;

&lt;p&gt;When my company gave me the news that China wouldn't be accepting teachers who were outside of the country for the fall semester, I wept again thinking, &lt;em&gt;why did I try so hard&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;I've asked myself that question over and over again in the months since.&lt;/p&gt;

&lt;p&gt;I keep returning to the same answer: I'm a helper. I want to help people. Even though I don't have much, I have a computer, and I will do anything I can to help people.&lt;/p&gt;

&lt;p&gt;My students.&lt;/p&gt;

&lt;p&gt;Werner.&lt;/p&gt;

&lt;p&gt;The homeless man.&lt;/p&gt;

&lt;p&gt;I can help people with tech.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Maybe you read these ten perspectives like a random assortment of items, dear Coder. Or maybe you read them like an algorithm, as though one shift in perspective invariably leads to the next.&lt;/p&gt;

&lt;p&gt;Sometimes I feel like I've been changing in a random, chaotic sort of way, because it took a painstaking amount of self-reflection to find the words to examine the changes in myself and print them to the page.&lt;/p&gt;

&lt;p&gt;But once they hit paper, I take comfort in reading them algorithmically. I observe and sort how circumstance acts upon me and how my reactions shape my circumstances. I find power and edification in observing my rational behavior, even thought it felt impulsive when it happened in real time.&lt;/p&gt;

&lt;p&gt;As coders, I think we take similar comfort in receiving an open-ended set of objectives and organizing them on a blank canvas in a way that others can read. &lt;/p&gt;

&lt;p&gt;And I think we take comfort in knowing others will understand and value the things we make. &lt;/p&gt;

&lt;p&gt;Maybe that's the theme: comfort in organization, comfort in making things for people, comfort in listening, refactoring, and sharing without expectation of anything in return.&lt;/p&gt;

&lt;p&gt;That's the gravity of coding.&lt;/p&gt;

&lt;p&gt;And I suppose that's where my meanderings end today, Dearest Coder.&lt;/p&gt;

&lt;p&gt;As always, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>career</category>
      <category>leadership</category>
      <category>todayilearned</category>
      <category>writing</category>
    </item>
    <item>
      <title>Scaffold Identity Pages with ASP.NET Core | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Wed, 26 May 2021 13:42:42 +0000</pubDate>
      <link>https://forem.com/piaomu/scaffold-identity-pages-with-asp-net-core-dear-coder-1e88</link>
      <guid>https://forem.com/piaomu/scaffold-identity-pages-with-asp-net-core-dear-coder-1e88</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;Let’s talk about the person who matters the most in our field.&lt;/p&gt;

&lt;p&gt;No, it’s not you (though you’re enduringly important to me, dear Coder).&lt;/p&gt;

&lt;p&gt;I’m talking about the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do I Represent the User in Code?
&lt;/h2&gt;

&lt;p&gt;I want the user to have a good user experience, so I build a model that inherits from AspNetCore’s IdentityUser. By doing this, I inherit a set of robust properties without having to write too much new code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create User Model and Inherit Properties from IdentityUser
&lt;/h2&gt;

&lt;p&gt;Let’s start with the User model:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvovv2pw910b9n7v7bi3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvovv2pw910b9n7v7bi3.png" alt="ToonUser Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my ToonSpace project, I create a model named “ToonUser” and add some custom properties that IdentityUser doesn’t already cover, including:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

FirstName
LastName
DisplayName
FullName
ImageData
ContentType


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I also inherit the properties of IdentityUser by using the Microsoft.AspNetCore.Identity namespace and inheriting from Identity user when I name the class:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbuwlrm1pgwsugbdoyo1p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbuwlrm1pgwsugbdoyo1p.png" alt="Inherit from IdentityUser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What properties does IdentityUser grant me access to? A lot.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfhnhhfqeyxl6awecw4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfhnhhfqeyxl6awecw4y.png" alt="Properties inherited from IdentityUser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With these properties appended to my ToonUser, I have the tools I need to allow users to register accounts and interact with my application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modify Startup.cs and ApplicationDbContext
&lt;/h2&gt;

&lt;p&gt;In my data folder, I access my ApplicationDbContext file and inherit IdentityDbContext of type ToonUser.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7q54si3z3em5pc7l8yo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7q54si3z3em5pc7l8yo.png" alt="Update ApplicationDbContext"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I add the ToonUser to my Identity service, along with Default UI and DefaultTokenProviders.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh8qam2aiav745v9ezo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh8qam2aiav745v9ezo8.png" alt="update Startup.cs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaffold Identity Pages
&lt;/h2&gt;

&lt;p&gt;Now I’m ready to scaffold Identity pages for user accounts. I add a Scaffolded Item in my Areas &amp;gt; Identity folder and select “Identity.” &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvbmucv0cvvglku5r626.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvbmucv0cvvglku5r626.png" alt="Scaffold Identity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I override all files and select ApplicationDbContext as my data context class. Once I add the scaffolded Identity pages, my Identity folder will be filled with boilerplate razor pages.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhog792n3cc2gc0xa5ru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhog792n3cc2gc0xa5ru.png" alt="Scaffolded Identity Pages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I access the code behind for the “register” view and add properties for First Name and Last Name because those properties are not the default with Identity pages. I also add fields to the View for the user to enter this information.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6iyrltle27vu5jbdokd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6iyrltle27vu5jbdokd1.png" alt="Modify Code Behind"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that I have registration pages scaffolded and augmented to fit my ToonUser model, users can register an account on my application.&lt;/p&gt;

&lt;p&gt;I hope these letters find you well, dearest Coder.&lt;/p&gt;

&lt;p&gt;Until next time, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>security</category>
      <category>tutorial</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Role-Based Security using Entity Framework (Part 1) | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Tue, 25 May 2021 12:45:09 +0000</pubDate>
      <link>https://forem.com/piaomu/role-based-security-using-entity-framework-part-1-dear-coder-4d6h</link>
      <guid>https://forem.com/piaomu/role-based-security-using-entity-framework-part-1-dear-coder-4d6h</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;If you're working on an application that allows users to register an account, you've likely encountered the issue of role-based security.&lt;/p&gt;

&lt;p&gt;What is role-based security and why do we need it?&lt;/p&gt;

&lt;p&gt;Say you're working on an application that allows users to share webcomics with each other. You've already built in the features that allow the user to securely upload photos to your database, and you've implemented features that allow users to register an account and log in.&lt;/p&gt;

&lt;p&gt;But now you need to ask what features should be accessible to any user regardless of if they've registered an account, what features should be accessible to registered users, and what features should be available to privileged users.&lt;/p&gt;

&lt;p&gt;This is where role-based security comes in.&lt;/p&gt;

&lt;p&gt;For the sake of my illustration, let's categorize users into four tiers of access:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;anonymous (unregistered) users&lt;/li&gt;
&lt;li&gt;registered users&lt;/li&gt;
&lt;li&gt;Moderators&lt;/li&gt;
&lt;li&gt;Administrators&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Anonymous User Authorizations
&lt;/h2&gt;

&lt;p&gt;By default, my application allows any user to see, interact with, and use any of the pages on my application.&lt;/p&gt;

&lt;p&gt;But what pages should anonymous users be able to see?&lt;/p&gt;

&lt;p&gt;As a general rule, landing pages and displays of publicly-available data are fine for anonymous end-users to see.&lt;/p&gt;

&lt;p&gt;Some developers may maintain applications that contain a large amount of sensitive data, however, which means it might be appropriate to refactor the application's default authorization.&lt;/p&gt;

&lt;p&gt;We can do this with some interplay between the &lt;code&gt;[Authorize]&lt;/code&gt; and &lt;code&gt;[AllowAnonymous]&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;But more on anonymous users later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registered Users
&lt;/h2&gt;

&lt;p&gt;Let's back up and talk about the &lt;code&gt;[Authorize]&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;If I want my application to handle uploads, it's in my best interest to deny anonymous users access to some of my views. I can do this with a simple keyword called "Authorize"&lt;/p&gt;

&lt;p&gt;To prompt a user to register and log in to see a View, I need to access the controller that handles the get and post http requests for the Views I want to authorize.&lt;/p&gt;

&lt;p&gt;To illustrate, let's look in my ToonSpace webtoons application, and access the Uploads controller.&lt;/p&gt;

&lt;p&gt;I don't want anonymous users to be able to upload to my website, so I need to make a small change under the "get" action by adding &lt;code&gt;[Authorize]&lt;/code&gt; above the action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wMYXDKHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/se5z34c683u8yrfr1kub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wMYXDKHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/se5z34c683u8yrfr1kub.png" alt="Get Create Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This simply ensures that only users who have registered an account and are logged in can access the "Create" view to upload something new to the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moderators and Administrators
&lt;/h2&gt;

&lt;p&gt;﻿I've grouped moderators and administrators together because the code for my Moderator and Administrator permissions is essentially the same. The only differences are discretionary. I grant some permissions to both roles and others to just the Administrator.&lt;/p&gt;

&lt;p&gt;So how do I grant special permissions to these roles?&lt;/p&gt;

&lt;p&gt;Just a few simple lines of text:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mtXdiUXe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvoqe97de6md8qys6qo2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mtXdiUXe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvoqe97de6md8qys6qo2.png" alt="Administrator Auth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To authorize a moderator as well, I simply add a comma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Authorize(Roles = "Administrator, Moderator"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've created the structure for role-based security. Any user may create an account and log in, and anonymous users are not allowed to post anything. But what if I want to set the default to allow anonymous users to post something (like a comment)? I can simply use the &lt;code&gt;[AllowAnonymous]&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;And what about these Administrator and Moderator roles? How do I differentiate between which users are in these roles?  Should anyone be allowed to sign up as an Administrator or Moderator?&lt;/p&gt;

&lt;p&gt;I'm sure you already know, dear Coder, that allowing the user to sign up as an Admin is probably not a great idea. What I can do instead, however, is "seed" a designated user as an Administrator or Moderator.&lt;/p&gt;

&lt;p&gt;But that will be the topic of my next letter.&lt;br&gt;
If you'd like to read more letters, you can find them at &lt;a href="http://www.dear-coder.com/"&gt;dear-coder.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Until next time, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>security</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Securely Handle User Uploads With Service Injection (MVC) | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Mon, 17 May 2021 12:57:36 +0000</pubDate>
      <link>https://forem.com/piaomu/securely-handle-user-uploads-with-service-injection-mvc-dear-coder-29dp</link>
      <guid>https://forem.com/piaomu/securely-handle-user-uploads-with-service-injection-mvc-dear-coder-29dp</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;In my last letter, I wrote about &lt;a href="https://dev.to/piaomu/four-rules-for-accepting-secure-user-uploads-to-a-postgressql-database-mvc-dear-coder-o9a"&gt;four rules&lt;/a&gt; to keep in mind while handling uploads from users in a web application. Today I want to give some step-by-step instructions on how to handle uploads while satisfying those rules.&lt;/p&gt;

&lt;p&gt;You might recall that I'm building an application called &lt;a href="https://dev.to/piaomu/create-a-relational-database-using-asp-net-core-mvc-dear-coder-3jj0"&gt;ToonSpace&lt;/a&gt; for users to share their webtoons with each other. Today, I'll build the service that will accomplish that goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Image Service Interface
&lt;/h2&gt;

&lt;p&gt;I create a new folder on the top level of my Solution Explorer named &lt;em&gt;Services&lt;/em&gt; and add a new public Interface &lt;em&gt;IImageService&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8y6f0nma5m1pq6j3e7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8y6f0nma5m1pq6j3e7k.png" alt="Services Folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This Interface will hold a task that Encodes the image from a user upload, a task that encodes an image from a url, a string that decodes the image, and a string that records the content type of the image.&lt;/p&gt;

&lt;p&gt;I name my service IImageService and add these four fields, making sure to declare the Interface is public.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyscjyn40iqx7v8y4qt8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyscjyn40iqx7v8y4qt8.png" alt="IImageService"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also add my AspNetCore.Http using directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspCore.Http;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Basic Image Service Concrete Class
&lt;/h2&gt;

&lt;p&gt;Once the interface is finished, I create a corresponding concrete class called BasicImageService that holds executing code for the interface.&lt;/p&gt;

&lt;p&gt;Inside my &lt;em&gt;Services&lt;/em&gt; folder, I create a class called BasicImageService.&lt;/p&gt;

&lt;p&gt;I add three using directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.Http;
using System.IO;
using System.Net.Http;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Let's look at what each of these methods actually allow me to do in the concrete class:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        public async Task&amp;lt;byte[]&amp;gt; EncodeImageAsync(IFormFile image)
        {
            if (image == null)
            {
                return null;
            }
            using var ms = new MemoryStream();
            await image.CopyToAsync(ms);
            return ms.ToArray();

        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;EncodeImageAsync&lt;/em&gt; encodes a user-submitted image from an upload control and converts the file to a byte array to be stored in my database. Later, I'll leverage the multi-part form-data feature to allow users to submit an image file within a form, which is why &lt;em&gt;EncodeImageAsync&lt;/em&gt; takes the IFormFile interface type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        public async Task&amp;lt;byte[]&amp;gt; EncodeImageURLAsync(string imageURL)
        {
            var client = new HttpClient();

            var response = await client.GetAsync(imageURL);

            Stream stream = await response.Content.ReadAsStreamAsync();

            var ms = new MemoryStream();
            await stream.CopyToAsync(ms);

            return ms.ToArray();

        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;EncodeImageURLAsync&lt;/em&gt; takes the &lt;em&gt;path&lt;/em&gt; to an image and turns it into a byte array to be used in a similar fashion to &lt;em&gt;EncodeImageAsync&lt;/em&gt;, storing an image in the database as a byte array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        public string DecodeImage(byte[] image, string contentType)
        {
            if (image == null)
            {
                return null;
            }
            var convertedImage = Convert.ToBase64String(image);
            return $"data:{contentType};base64,{convertedImage}";
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two methods dealt with encoding an image to store in my database. &lt;em&gt;DecodeImage&lt;/em&gt; allows me to convert the stored data into a base64 string and pull it from the database to display as an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        public string RecordContentType(IFormFile image)
        {
            if (image == null)
            {
                return null;
            }
            return image.ContentType;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I need to record the &lt;em&gt;ContentType&lt;/em&gt; (png, jpeg, etc.) so I can properly formulate the string to display the image.&lt;/p&gt;

&lt;p&gt;The finished Concrete Class looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsx4sovp8c1vifqn5yh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsx4sovp8c1vifqn5yh3.png" alt="BasicImageService"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Register Basic Image Service
&lt;/h2&gt;

&lt;p&gt;Now that I've built my interface and corresponding concrete class for my Basic Image Service, I have to register it as a service in my Startup so I can inject it across the project. &lt;/p&gt;

&lt;p&gt;I simply access my Startup file in my Solution Explorer and scroll to the _ConfigureServices method:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vp4p3jz11x3i5me651m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vp4p3jz11x3i5me651m.png" alt="Startup.cs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I add my Basic Image Service to my list of services by adding &lt;code&gt;using ToonSpace.Services&lt;/code&gt; to the top of the document and adding my service to the list of services like with the IImageService interface and BasicImageService concrete class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddScoped&amp;lt;IImageService, BasicImageService&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now my service is ready to be used throughout the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inject Service into Controller
&lt;/h2&gt;

&lt;p&gt;I've registered an image service that will allow users to securely upload their webtoons to my application, so now comes the fun part! I inject my service into the controller by adding a using directive, constructor, and parameters:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmra3s6nuxhmjtva1imj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmra3s6nuxhmjtva1imj5.png" alt="Inject Image Service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the Image Upload to the Form
&lt;/h2&gt;

&lt;p&gt;I need to jump over to the View where the user is going to upload so I can instruct the controller what to do when the user uploads.&lt;/p&gt;

&lt;p&gt;I access the Create scaffolded View in my Uploads Views folder to access the form that has already been built for me.&lt;/p&gt;

&lt;p&gt;The first thing I need to do is change the encode type to &lt;code&gt;enctype="multipart/form-data"&lt;/code&gt; which is an HTML spec that allows the form to now accept uploads instead of just fields.&lt;/p&gt;

&lt;p&gt;Then, scroll to the Image div and add an Image Id, a type of "file", and a "form-control-file" class (for styling).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            &amp;lt;div class="form-group"&amp;gt;
                &amp;lt;label asp-for="Image" class="control-label"&amp;gt;&amp;lt;/label&amp;gt;
                &amp;lt;input id="Image" type="file" asp-for="Image" class="form-control-file" /&amp;gt;
                &amp;lt;span asp-validation-for="Image" class="text-danger"&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Instructions in Create Action of Controller
&lt;/h2&gt;

&lt;p&gt;I open my UploadsController to the Create Action and remove &lt;em&gt;Image&lt;/em&gt; and &lt;em&gt;ContentType&lt;/em&gt; from the Bind. I add add IFormFile Image as an argument in the Create Method, which Microsoft.AspNetCore.Http allows me to do. I add &lt;code&gt;Microsoft.AspNetCore.Http&lt;/code&gt; to my using directives.&lt;/p&gt;

&lt;p&gt;The Bind now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public async Task&amp;lt;IActionResult&amp;gt; Create([Bind("Id,GenreId,Title,Artist,Created,Image,ContentType")] Upload upload, IFormFile Image)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then set the upload image and content type equal to the data coming in from the image service if the model state is valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                upload.ContentType = _imageService.ContentType(Image);
                upload.Image = await _imageService.EncodeImageAsync(Image);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user's upload will now save to the database after I've written these lines of code in the Create Action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Display The User's Image in the View
&lt;/h2&gt;

&lt;p&gt;The only thing I have left to do is spin up the user's image from the database and display it in the View. To do this, I access my Views folder and find the "Details" view under "Uploads."&lt;/p&gt;

&lt;p&gt;I write some quick markup for illustration purposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@model ToonSpace.Models.Upload
@using ToonSpace.Services
@inject IImageService _imageService

@{
    ViewData["Title"] = "Details";
}

&amp;lt;h1&amp;gt;Details&amp;lt;/h1&amp;gt;

&amp;lt;div&amp;gt;
    &amp;lt;h4&amp;gt;Upload&amp;lt;/h4&amp;gt;
    &amp;lt;hr /&amp;gt;

    &amp;lt;div class="card"&amp;gt;
        &amp;lt;div class="col-8"&amp;gt;
            &amp;lt;img id="Profile" class="img-fluid" src="@_imageService.DecodeImage(Model.Image, Model.ContentType)" /&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, all the user needs to do is upload an image to the database and they will be able to see the image displayed in the Details View.&lt;/p&gt;

&lt;p&gt;There's much more to be done to make this platform functional and secure, but today's letter is already longer than usual, and so I'll leave you to rest.&lt;/p&gt;

&lt;p&gt;Godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>csharp</category>
      <category>tutorial</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Four Rules for Accepting Secure User Uploads to a PostgresSQL Database (MVC) | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Mon, 10 May 2021 13:01:14 +0000</pubDate>
      <link>https://forem.com/piaomu/four-rules-for-accepting-secure-user-uploads-to-a-postgressql-database-mvc-dear-coder-o9a</link>
      <guid>https://forem.com/piaomu/four-rules-for-accepting-secure-user-uploads-to-a-postgressql-database-mvc-dear-coder-o9a</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;In my last letter, I wrote about how I used enums to populate a dropdown list of genres from which a user can select to categorize their webtoons in the ToonSpace database.&lt;/p&gt;

&lt;p&gt;But what about the webtoons?&lt;/p&gt;

&lt;p&gt;I haven't allowed the user to upload their own files to the database yet, and that's for good reason: I'm scared.&lt;/p&gt;

&lt;p&gt;You should be too.&lt;/p&gt;

&lt;p&gt;Okay, maybe I'm being a little dramatic. But only a little.&lt;/p&gt;

&lt;p&gt;Whenever you're allowing users to upload to your database, security should be your highest concern. For our purposes, that means two things: safeguard your database from insecure uploads and prompt the user to register an account before they are able to upload anything to the database.&lt;/p&gt;

&lt;p&gt;We'll discuss registration at a later date, but that's the subject of a different letter.&lt;/p&gt;

&lt;p&gt;For now, let's dig into the four requirements for accepting secure image uploads from the user.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Rules
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Rule Number One: Do Not Accept the filename the User Gives You
&lt;/h3&gt;

&lt;p&gt;You must change the name during the upload process. This prevents the user from wittingly or unwittingly using common problematic symbols in directories and filenames like spaces and slashes from causing problems.&lt;/p&gt;

&lt;p&gt;I must change the name during the upload process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule Number Two: Do Not Accept the Pathing that the User Gives You
&lt;/h3&gt;

&lt;p&gt;A user might try to upload and wittingly or unwittingly upload a file to a folder that I don't want them to access. This could cause all kinds of problems if I need to retrieve the file path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule Number Three: Investigate the Content of the User's Upload
&lt;/h3&gt;

&lt;p&gt;Just because a user uploads a file with a "png" extension doesn't necessarily mean the file is actually a png image. I need to safeguard my database from accepting unwanted file types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule Number Four: Turn Off Execution Rights in the Upload Folder
&lt;/h3&gt;

&lt;p&gt;This one is the most critical because I don't want my user to be able to execute any impermissible operations that could damage or otherwise maliciously attack my database or application. The user should not be able to execute anything when they upload.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Solution
&lt;/h1&gt;

&lt;p&gt;I've considered three ways I can allow the user to upload their images to the database, each with their own security concerns. I'll outline them to you and tell you which I eventually settled on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method One: Allow the User to Upload Directly to the Server
&lt;/h3&gt;

&lt;p&gt;I could create an image folder in the wwwroot directory and programatically direct the user to upload to it, but this method doesn't scale well, and requires a lot of extra code to satisfy my four rules for secure uploads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method Two: Use a Third-Party Cloud Service to Handle the Upload
&lt;/h3&gt;

&lt;p&gt;This is the most recent method for handling a secure upload, and it comes with plenty of advantages (namely ease, speed, and peace of mind),  but third-party hosting with Azure or Amazon can also cost more money than a developer is willing to pay for a small project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method Three: Upload the Image and Store them as Byte Arrays
&lt;/h3&gt;

&lt;p&gt;This method is the simplest and most ideal because I don't need to use the name or path a user gives me, and the file cannot execute. I'm just breaking down the image into a stream of bytes and decoding it again to display it.&lt;/p&gt;

&lt;p&gt;However, I still have to investigate the content of the file to verify that it's actually an image file.&lt;/p&gt;

&lt;p&gt;I can accomplish all of these goals by creating an interface and basic image service to handle user uploads.&lt;/p&gt;

&lt;p&gt;But again, dearest Coder, coding and implementing my image service will be the subject of my next letter.&lt;/p&gt;

&lt;p&gt;Until next time, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Create a Relational Database using ASP.NET Core (MVC) Pt. 3 | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Tue, 04 May 2021 12:57:21 +0000</pubDate>
      <link>https://forem.com/piaomu/create-a-relational-database-using-asp-net-core-mvc-pt-3-dear-coder-3o65</link>
      <guid>https://forem.com/piaomu/create-a-relational-database-using-asp-net-core-mvc-pt-3-dear-coder-3o65</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;I have a problem.&lt;/p&gt;

&lt;p&gt;If you read my last letter, you might recall I &lt;a href="https://dev.to/piaomu/creating-a-relational-database-using-asp-net-core-mvc-pt-2-dear-coder-35h7"&gt;used Entity Framework&lt;/a&gt; to save a lot of time scaffolding my Controllers and Views for the Genres and Uploads Models for my ToonSpace application.&lt;/p&gt;

&lt;p&gt;But I signed my last letter with a minor bug:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjai35goa5fdrut1z9a01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjai35goa5fdrut1z9a01.png" alt="Blank Dropdown Bug"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My GenreId dropdown (which should just display "Genre", but I'll get to that later) displays blank. This isn't a big deal though, as it's simply a result of Entity Framework trying to anticipate the purpose of that field. But it isn't functional.&lt;/p&gt;

&lt;p&gt;I want to provide the user with a pre-populated list of options for the Genre of their uploaded webtoons, and I achieve this with &lt;em&gt;enums&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Enums to Create a Dropdown
&lt;/h2&gt;

&lt;p&gt;I first create a new folder on the top level of my project in the &lt;em&gt;Solutions Explorer&lt;/em&gt; called "enums" and add a new class to it called GenreName.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nlk8kpi6wmy3ai6kblt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nlk8kpi6wmy3ai6kblt.png" alt="Enum Folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;enum&lt;/em&gt; type is essentially a comma-separated list of strings, zero-indexed, and alphanumerical. I use the indexed property of my enum to function as the GenreId for each Upload object.&lt;/p&gt;

&lt;p&gt;I declare it as a public enum instead of a class and create five options for a user to choose from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz36hxq651r94hymujhc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz36hxq651r94hymujhc6.png" alt="GenreName enum"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next I add GenreName as a property of my upload Model, making sure to a using directive for GenreName in my using directives above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqeffcyccso66ryyuy8q2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqeffcyccso66ryyuy8q2.png" alt="Updated Uploads Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Display Enum Data in Dropdown
&lt;/h2&gt;

&lt;p&gt;I make some small changes to my Create and Edit Views in the Uploads View folder, changing all instances of GenreId to GenreNames and amending the asp-items property to connect it to my enum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            &amp;lt;div class="form-group"&amp;gt;
                &amp;lt;label asp-for="GenreName" class="control-label"&amp;gt;&amp;lt;/label&amp;gt;
                &amp;lt;select asp-for="GenreName" class ="form-control" asp-items="Html.GetEnumSelectList&amp;lt;GenreName&amp;gt;()"&amp;gt;&amp;lt;/select&amp;gt;
            &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I make sure to add a using directive to bring in my Enums folder as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7uigwkdk86bzti53l5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7uigwkdk86bzti53l5m.png" alt="@using ToonSpace.Enums"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before building the solution, I migrate my changes to the database and update it.&lt;/p&gt;

&lt;p&gt;Finally, I build the solution and check that my new dropdown menu works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy6ipk6mcd30n7fljuwn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy6ipk6mcd30n7fljuwn.png" alt="It works!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A brief Note on Data Annotations
&lt;/h2&gt;

&lt;p&gt;If you're like me, dear Coder, you might find the Pascal case of &lt;em&gt;GenreName&lt;/em&gt; and &lt;em&gt;SciFi&lt;/em&gt; in the dropdown to be off-putting from the end user's perspective. &lt;/p&gt;

&lt;p&gt;We can fix these cosmetic issues by leveraging Data Annotations.&lt;/p&gt;

&lt;p&gt;Though enums are alphanumerical, I can still use a hyphen within a data annotation to display the enum's value in the View. I simply add this using directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.ComponentModel.DataAnnotations;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this display text above the index of my desired value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Display(Name = "Sci-Fi")]
SciFi,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is something like this on the page:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbkbi1r0azsgeos5kfs6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbkbi1r0azsgeos5kfs6c.png" alt="Data Annotations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I simply use the same using directive and display syntax in my Upload model to clean up the Genre Name tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqfte6o4012jy35y7y19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqfte6o4012jy35y7y19.png" alt="Final Upload Model"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Finally, our bugs are fixed and the data displays nicely for the end user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1imxwbk8mman3e67saxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1imxwbk8mman3e67saxr.png" alt="All Done"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope my letters are finding you well, dearest Coder, and I look forward to your swift replies.&lt;/p&gt;

&lt;p&gt;Until then, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>database</category>
      <category>tutorial</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Create a Relational Database using ASP.NET Core (MVC) Pt. 2 | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Sun, 02 May 2021 17:52:56 +0000</pubDate>
      <link>https://forem.com/piaomu/creating-a-relational-database-using-asp-net-core-mvc-pt-2-dear-coder-35h7</link>
      <guid>https://forem.com/piaomu/creating-a-relational-database-using-asp-net-core-mvc-pt-2-dear-coder-35h7</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;Earlier this week, I &lt;a href="https://dev.to/piaomu/create-a-relational-database-using-asp-net-core-mvc-dear-coder-3jj0"&gt;wrote to you&lt;/a&gt; about a webtoon application I'm building using ASP.NET Core and PostGresSQL. &lt;/p&gt;

&lt;p&gt;I told you about my process for setting up the project and connecting it to a Postgres database. Today I want to expound on that thought. Let's talk about building models and scaffolding controllers/Views.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Little Pre-Planning
&lt;/h2&gt;

&lt;p&gt;As with any application I build using MVC, I need to take inventory of what models I will need to give structure to my data. In server-side terms, what rows and columns do I need to define? &lt;/p&gt;

&lt;p&gt;In my last letter, I defined the goals of this project: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload my webcomics to a database.&lt;/li&gt;
&lt;li&gt;Sort and display them by genre, date, and popularity.&lt;/li&gt;
&lt;li&gt;Allow verified users to upload their own content safely and securely to my database with the same capabilities.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these goals in mind, I have a clear idea of which models I need to build and what properties I need to give them to achieve my goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the Models
&lt;/h2&gt;

&lt;p&gt;In my Models folder, I create two classes: one for user uploads and one for upload's genre.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;public class Upload&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0w9tXuBw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9yvd9oyouqqom5jzrhze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0w9tXuBw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9yvd9oyouqqom5jzrhze.png" alt="Upload Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;public class Genre&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y24HqcWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0aakeyq3dw8ncv4nfxmp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y24HqcWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0aakeyq3dw8ncv4nfxmp.png" alt="Genre Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entity Framework Code First naming conventions make it easy for me to create a primary key, so I simply add an "Id" property to both the Genre and Upload class.&lt;/p&gt;

&lt;p&gt;I elect to create these two models so I can sort uploads using their primary keys in the database, but I also leverage the the genre's foreign key to identify uploads by genre, as I'll illustrate later.&lt;/p&gt;

&lt;p&gt;But before that, let's make some magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaffold the Controller and Views
&lt;/h2&gt;

&lt;p&gt;Entity Framework comes with some huge time-savers, including scaffolded items. I use scaffolding to populate Controller and View templates by simply locating the Controllers folder in my Solutions Explorer, hovering over the "Add" button, and selecting &lt;em&gt;New Scaffolded Item&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RWyqoutl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvr3bi66jmnsn8jou7nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RWyqoutl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvr3bi66jmnsn8jou7nc.png" alt="Scaffolding"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to create the Controller &lt;em&gt;and&lt;/em&gt; the View for my scaffolded content, so I select &lt;em&gt;MVC Controller with views, using Entity Framework&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L0sgrAo5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6g9qsjiwk8wy47bc9r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L0sgrAo5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6g9qsjiwk8wy47bc9r4.png" alt="Scaffolding Controller With Views Entity Framework"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before I finalize my scaffolding, I make sure to select "Genre" as my Model class for Genre and "Upload" as my Model Class for upload. I also make sure each have the Data context class as ApplicationDbContext (ToonSpace.Data) where "ToonSpace" is the name of my project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zY4Khg6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgfc231op05xg1tcvxi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zY4Khg6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgfc231op05xg1tcvxi9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The default Controller name is always the Model name, but plural. In the case of the picture above, the Model name is "Genre" but the default Controller name is "GenresController." As a matter of consistency, I always use Entity Framework's default Controller Name.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Once I finish, I have three controllers in my Controllers folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aHbQaq2U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4l7w2zohiptw4266ret.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aHbQaq2U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4l7w2zohiptw4266ret.png" alt="Finished Controllers Folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I check my Views folder to see I have five Views a Genres folder and five Views in an Uploads folder: Create, Delete, Details, Edit, and Index.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0NFdYLc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v5zzz5ckulopgloi0dz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0NFdYLc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v5zzz5ckulopgloi0dz4.png" alt="Views folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entity Framework has scaffolded a basic skeleton of Controllers and Views for all of the code and data that I built out in my Models. I open my Package Manager Console and add a migration and update my Postgres database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DfSv0Im1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5b0cf2p0q7ykkhvo5isv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DfSv0Im1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5b0cf2p0q7ykkhvo5isv.png" alt="migration complete"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Edit Navbar to Navigate to New Views
&lt;/h2&gt;

&lt;p&gt;I edit the navbar by locating the Layout View under Shared. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ONqfDrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swt1w2cp4v7nktu58xri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ONqfDrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swt1w2cp4v7nktu58xri.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I add two links to the navbar: one for Genres and one for Uploads. I connect them to their corresponding controller by setting asp-controller equal to "Genres" and "Uploads" respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3J7XqhkZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zc7odxi7xcxmc944hey0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3J7XqhkZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zc7odxi7xcxmc944hey0.png" alt="create nav links"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Solution and Check Views
&lt;/h2&gt;

&lt;p&gt;Now I build my solution and check the application by launching IIS Express to make sure my controller is communicating properly between my Models and Views. &lt;/p&gt;

&lt;p&gt;I check my Uploads Index page, which displays a table of objects and their properties from my Model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Aqdcfce--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udyk2ukhtzw9jtg06bby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Aqdcfce--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udyk2ukhtzw9jtg06bby.png" alt="Uploads Index"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking "Create New" displays my "Create" View, which allows the user to create a new instance of my Uploads class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lF2TbALq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqxmu5ier1umapyxt806.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lF2TbALq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqxmu5ier1umapyxt806.png" alt="Create Upload View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there's one problem: the field for "GenreId" was pre-constructed with a drop-down option and validation, which means the user cannot complete the creation of an object.&lt;/p&gt;

&lt;p&gt;The problem is a simple fix, but one that will serve as the subject of my next letter.&lt;/p&gt;

&lt;p&gt;So until next time dearest Coder, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>database</category>
      <category>postgres</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create a Relational Database using ASP.NET Core (MVC) | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Thu, 29 Apr 2021 13:35:25 +0000</pubDate>
      <link>https://forem.com/piaomu/create-a-relational-database-using-asp-net-core-mvc-dear-coder-3jj0</link>
      <guid>https://forem.com/piaomu/create-a-relational-database-using-asp-net-core-mvc-dear-coder-3jj0</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;I made a thing and I want to share it with you.&lt;/p&gt;

&lt;p&gt;A few months ago, I started an &lt;a href="https://www.instagram.com/universal_basic_insecurity/" rel="noopener noreferrer"&gt;Instagram page&lt;/a&gt; where I share some comics that I draw. And I thought, "Wouldn't it be fun to make my own database where I can control the flow of content without my hack-job humor getting swallowed by the infinite-Insta-algorithm?"&lt;/p&gt;

&lt;p&gt;So I decided to create a project that allows me to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload my web comics to a database.&lt;/li&gt;
&lt;li&gt;Sort and display them by genre, date, and popularity.&lt;/li&gt;
&lt;li&gt;Allow verified users to upload their own content safely and securely to my database with the same capabilities.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're coding along, you need a couple of prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Microsoft Studio 2019&lt;/li&gt;
&lt;li&gt;PostgresSQL v13&lt;/li&gt;
&lt;li&gt;PGAdmin 4 v5.2&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a new ASP.NET Core MVC App in Visual Studio
&lt;/h2&gt;

&lt;p&gt;Let's start with a brand new project in Visual Studio using the ASP.Net Core MVC Web App template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6vf1d4enqammrvp4f7p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6vf1d4enqammrvp4f7p.png" alt="ASP.Net Core Web APP (Model-View-Controller)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under Additional Information, I select "Individual Accounts" as my Authentication Type. I also want to enable Razor runtime compilation.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnybg2b3x539a97nvqor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnybg2b3x539a97nvqor.png" alt="Additional Information checks"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Clear Migrations Folder and Download Requisite NuGet Packages
&lt;/h2&gt;

&lt;p&gt;I want to initiate a new migration when I'm ready to set up my database, so I need to delete the Migrations folder in my Solutions Explorer that comes boilerplate with this template.&lt;/p&gt;

&lt;p&gt;Once that's done, I right-click the top level of my project to manage NuGet packages. This is where I bring in all the sweet sauce that allows me to build my database.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiof7dgtwrijkykyfer1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiof7dgtwrijkykyfer1i.png" alt="Npgsql &amp;amp;&amp;amp; Npgsql.EntityFrameworkCore.PostgresSQL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I make sure I've downloaded these dependencies before writing any code.&lt;/p&gt;

&lt;p&gt;I open the Startup.cs file at the bottom of my Solution Explorer to add a Using statement to bring in my Npgsql. Then I delete the boilerplate options.Use text and insert options.UseNpgsql.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foedsanmjv50vs483fq8q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foedsanmjv50vs483fq8q.png" alt="Startup.cs text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  First Data Migration
&lt;/h2&gt;

&lt;p&gt;Now that I've brought in my NpgSQL, I can initialize my Identity migration to create the data structure that will feed into the database.&lt;/p&gt;

&lt;p&gt;I open the Package Manager Console by clicking Tools &amp;gt; NuGet Package Manager &amp;gt; Package Manager Console. Then I initialize the first migration with the following code: &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dus6v0fj1ob4p40k46w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dus6v0fj1ob4p40k46w.png" alt="Identity Migration"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create Postgres Database
&lt;/h2&gt;

&lt;p&gt;I'm almost ready to create my database, but first I need to change my connection string to wire Visual Studio to my postgres server.&lt;/p&gt;

&lt;p&gt;I delete the default ConnenctionStrings and enter this string of code in my appsettings.json file near the bottom of my Solutions Explorer with the name of my project as the  database and my database password as the password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ConnectionStrings": { "DefaultConnection": "Server=localhost; Port=5432; Database=[PROJECT-NAME]; User Id=postgres; Password=********" },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I open my Package Manager Console again, this time execute the command, update-database.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zfjce959hic2fo17388.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zfjce959hic2fo17388.png" alt="update-database"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; I encountered an error message after the build succeeded. This was rectified after I opened pgAdmin, logged in to my server, and refreshed the server.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu7xrlsihqyjdwa2fax8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu7xrlsihqyjdwa2fax8.png" alt="Possible Error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the Database
&lt;/h2&gt;

&lt;p&gt;As a final check, I enter pgAdmin and check that my ToonSpace server is live and working.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7dxg2x2raflfujrs4eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7dxg2x2raflfujrs4eg.png" alt="Server Success!"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;And that's all there is to setting up a simple server using postgresSQL in an MVC template. &lt;/p&gt;

&lt;p&gt;In this letter, I've only shared the beginning--I'm a long way off from having a functional web cartoon app, but my fingers are fading, and let's be real: our squirrel brains don't have the attention span for a 40 minute read.&lt;/p&gt;

&lt;p&gt;So until next time, dearest Coder, godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity Clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>postgres</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>C# Classes, Objects, and Class Members Explained by Dan Harmon's "Community" | Dear Coder</title>
      <dc:creator>Kasey Wahl</dc:creator>
      <pubDate>Tue, 27 Apr 2021 15:25:51 +0000</pubDate>
      <link>https://forem.com/piaomu/c-classes-objects-and-class-members-explained-by-dan-harmon-s-community-dear-coder-225f</link>
      <guid>https://forem.com/piaomu/c-classes-objects-and-class-members-explained-by-dan-harmon-s-community-dear-coder-225f</guid>
      <description>&lt;p&gt;Dear Coder,&lt;/p&gt;

&lt;p&gt;If you're a complete beginner or transitioning into object-oriented programming (OOP) you might have already discovered that &lt;em&gt;classes&lt;/em&gt;, &lt;em&gt;objects&lt;/em&gt;, and &lt;em&gt;class members&lt;/em&gt; are &lt;em&gt;EVERYTHING&lt;/em&gt;. If you're anything like me, you might find that dizzying at first.&lt;/p&gt;

&lt;p&gt;But don't worry, Coder. We got this with a little help from the folks at Greendale Community College. After all, you know what they say at Greendale: coding is nothing but the abstraction of American pop culture references.&lt;/p&gt;

&lt;p&gt;Er, something like that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is OOP?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Procedural programming&lt;/em&gt; emphasizes writing procedures or methods that perform operations on data. &lt;em&gt;Object-oriented&lt;/em&gt; programming is about creating objects that contain data and procedures.&lt;/p&gt;

&lt;p&gt;In Pierce Hawthorne terms, OOP is about THINGS doing stuff and procedural is about DOING stuff to things. Nouny code vs. verby code.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-fpAc768iJo"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;Pierce trying to figure out OOP&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For us OOP people, that means we need to understand how to create objects out of words so we can &lt;em&gt;describe&lt;/em&gt; what they do and how they're supposed to do it. We do that using classes, objects, and class members.&lt;/p&gt;


&lt;h2&gt;
  
  
  Classes
&lt;/h2&gt;

&lt;p&gt;Classes and objects are the terms we use code a thing into existence. But what do they look like, and how can we use them in our code? Say hello to our ethnically neutral class-cot:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ANfVHstArQ0"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;class HumanBeing&lt;/em&gt; { }&lt;/p&gt;

&lt;p&gt;A class is the broadest definition of a thing. In this case, we'll use it to create a HumanBeing using the "class" keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class HumanBeing
{}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it: a human being. &lt;/p&gt;

&lt;p&gt;Sorta. &lt;/p&gt;

&lt;p&gt;But we've only declared that HumanBeing exists. What kind of features define ANY HumanBeing?&lt;/p&gt;




&lt;h2&gt;
  
  
  Class Members
&lt;/h2&gt;

&lt;p&gt;We've declared a class of HumanBeing, so now let's give it a little shape using &lt;em&gt;fields&lt;/em&gt; and &lt;em&gt;methods&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class HumanBeing
{
public string Name; // field
public int Age; // field
public string Major; // field
public bool InStudyGroup; //field
public void tellsJoke(); // method
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;fields&lt;/em&gt; in our HumanBeing object are pieces of data that describe what a HumanBeing is. They're the "adjectives" and "nouns" that give it shape.&lt;/p&gt;

&lt;p&gt;The tellsJoke() method is a procedural, executable piece of code that allows our HumanBeing to &lt;em&gt;do&lt;/em&gt; something. &lt;em&gt;Community&lt;/em&gt; is a funny show. The HumanBeings at Greendale all use the tellsJoke() method.&lt;/p&gt;

&lt;p&gt;And that's an important thing to note: all of the characters in &lt;em&gt;Community&lt;/em&gt; are HumanBeings, but not all HumanBeings are on the show &lt;em&gt;Community&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Duh, right?&lt;/p&gt;

&lt;p&gt;Good! You already understand the fundamental difference between &lt;em&gt;classes&lt;/em&gt; and &lt;em&gt;objects&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Objects
&lt;/h2&gt;

&lt;p&gt;Every ounce of my Millenial angst adores Pierce Hawthorne, but how do I represent him in code? &lt;/p&gt;

&lt;p&gt;The good news is, we're already halfway there. We'll use our HumanBeing template (class) to create a single instance of HumanBeing (object) called "Pierce" with dot notation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; class HumanBeing
{
public string Name; // field
public int Age; // field
public string Major; // field
public bool InStudyGroup; //field
public void tellsJoke(); // method

static void Main(string[] args)
   {
   HumanBeing Pierce = new HumanBeing();
   Pierce.Name = "Pierce Hawthorne";
   Pierce.Age = 65;
   Pierce.Major = "undeclared";
   Pierce.InStudyGroup = true;
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we've given some life to one instance of our HumanBeing class. He looks something like this. Can you see him? &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I63YfuGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fagqe7gwewm18eozn0c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I63YfuGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fagqe7gwewm18eozn0c.jpg" alt="HumanBeing Pierce"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use the same HumanBeing class to make any number of instances of itself. Just for fun, let's build some of the cast of &lt;em&gt;Community&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; class HumanBeing
{
public string Name; // field
public int Age; // field
public string Major; // field
public bool InStudyGroup; //field
public void tellsJoke(); // method

static void Main(string[] args)
   {
   HumanBeing Winger= new HumanBeing();
   Winger.Name = "Jeff Winger";
   Winger.Age = 32;
   Winger.Major = "Education";
   Winger.InStudyGroup = true;

   HumanBeing Britta = new HumanBeing();
   Britta.Name = "Britta Perry";
   Britta.Age = 30;
   Britta.Major = "Psychology";
   Britta.InStudyGroup = true;

   HumanBeing Starburns = new HumanBeing();
   Starburns.Name = "Alex Osbourne";
   Starburns.Age = 39;
   Starburns.Major = "undeclared";
   Starburns.InStudyGroup = false;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not too bad, yeah?&lt;/p&gt;

&lt;p&gt;We started by building a class with class members, then created several instances of that class called objects with more specific characteristics:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RNUKnuQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xl1pr7xf4mgj32iuiyeq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RNUKnuQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xl1pr7xf4mgj32iuiyeq.png" alt="classes and objects"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;There you have it in the simplest, Greendale-iest terms. &lt;/p&gt;

&lt;p&gt;That's all from me today, dearest Coder. Godspeed in your keystrokes.&lt;/p&gt;

&lt;p&gt;Clickity-clacks,&lt;/p&gt;

&lt;p&gt;Kasey&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
