<?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>DEV Community: Panji Kristi Prawiro</title>
    <description>The latest articles on DEV Community by Panji Kristi Prawiro (@prawiropanji).</description>
    <link>https://dev.to/prawiropanji</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%2F1430637%2Fae4cf2e0-27c6-4ff3-9ea5-5b03549a7a03.jpeg</url>
      <title>DEV Community: Panji Kristi Prawiro</title>
      <link>https://dev.to/prawiropanji</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prawiropanji"/>
    <language>en</language>
    <item>
      <title>Logging in ASP.NET Core</title>
      <dc:creator>Panji Kristi Prawiro</dc:creator>
      <pubDate>Sat, 21 Sep 2024 07:24:18 +0000</pubDate>
      <link>https://dev.to/prawiropanji/logging-in-aspnet-core-3i2c</link>
      <guid>https://dev.to/prawiropanji/logging-in-aspnet-core-3i2c</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;As a Developer there is no feeling that compares to the mix of emotions we experience after developing our application: relief, excitement, delight, and occasionally even tears (tears of joy). Because we have put our time and hard work into developing a fully functional application to solve a problem.&lt;/p&gt;

&lt;p&gt;In the development stage, we want to ensure our application runs perfectly without a bug. We tested our application by running it in debug mode and verifying all features work as expected, or maybe you have created a unit test and integration test for the project and ensured all running tests passed.&lt;/p&gt;

&lt;p&gt;Then we are ready to move to the next stage to ship our code into production, we deploy the application, and we think that our task is done. After a while, users of our application report that they encounter an error when using our application. It feels bummer, right? We have made sure that our code doesn't have bugs, and now it seems hard to identify the root cause of the problem because we cannot use debugging mode in production.&lt;/p&gt;

&lt;p&gt;You must know that in a production environment, something can go wrong that isn't directly caused by your code, issues can arise from this unexpected error such as network timeouts, database connectivity issues, or third-party API failures.&lt;br&gt;
The question is how to identify this problem that can arise in our running application in a real-time. Logging come to the rescue&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging
&lt;/h2&gt;

&lt;p&gt;Logging is recording all the events that occur in our running application. It can create a log message of error or maybe just information on execution flow. These log messages can be saved and looked at in various destinations such as the console, file, database, monitoring tool, etc. &lt;/p&gt;

&lt;p&gt;The real question is: what is the best approach to creating logging into our apps? Are you still creating a logging mechanism by creating a file and writing a text in the file manually by yourself? &lt;/p&gt;

&lt;p&gt;My best advice is to never manually create a logging system. It's a waste of time, and it might not have a great capability like a logging framework can offer, like structured logging (we'll talk more about the latter). In ASP.NET Core, there is a built-in logging framework that is auto-enabled, and you can use it right away. Before we create our user-defined log message, you must know several log levels indicate the severity of events in your application, there are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trace&lt;/strong&gt;: Use for highly detailed, step-by-step diagnostic information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug&lt;/strong&gt;: Use for development and debugging purposes, logging detailed internal state information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Information&lt;/strong&gt;: Use for general operational events that provide insight into the application's normal behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warning&lt;/strong&gt;: Use for issues that may not be immediately harmful but could lead to problems if not addressed. Like in the "else" case, if you insert new data into the database with EF, you should expect to get the number of inserted data, but instead, you get 0, which means there is no row inserted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error&lt;/strong&gt;: Use for significant problems that prevent specific functionalities but do not cause the entire application to fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Critical&lt;/strong&gt;: Use for severe issues that require immediate attention and could cause the entire application or system to fail. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, built-in logging in ASP.NET Core has 3 providers (destination where the log message is printed): console, debug, and EventLog (Windows Only).&lt;/p&gt;

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


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

&lt;p&gt;If we look at the console kestrel above, by default the minimum log level is set to Information. Hence the Trace and Debug level is not printed. You can change the behavior by changing the configuration in appsettings.json&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsxye688yluxxjwzi3ux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsxye688yluxxjwzi3ux.png" alt="log in console with trace minimum log level " width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We set the minimum log level into "&lt;code&gt;trace&lt;/code&gt;" so it is successful to print log messages from &lt;code&gt;trace&lt;/code&gt;and &lt;code&gt;debug&lt;/code&gt; and above severity level events. But how to use logger in other than program files like in controller, service, repository, and other files? You can do it by injecting it into the method or constructor right away without needing to configure and register the logging service in the IoC Container beforehand.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
  

&lt;p&gt;You can ask the IoC container to inject &lt;code&gt;ILogger&lt;/code&gt;object and you can store the injected logger object as a field and then use it anytime you want to create a log event. If you notice there is a message template with a placeholder (curly brace) in the log event to capture dynamic values as &lt;strong&gt;structured logging&lt;/strong&gt; instead of embedding them directly into the log message as plain text. This offers benefit for easy to search and analysis logs (we will talk about it later) &lt;/p&gt;
&lt;h2&gt;
  
  
  HTTP Logging
&lt;/h2&gt;

&lt;p&gt;It's important to log information about incoming HTTP requests and HTTP responses so you can identify the incoming request.&lt;/p&gt;

&lt;p&gt;HTTP logging captures details about each incoming HTTP request and outgoing response. This includes information such as the request path, method (GET, POST, etc.), headers, and response status codes. This makes it easier to trace the flow of requests through your application and identify issues like incorrect routing or faulty response.&lt;/p&gt;

&lt;p&gt;how to configure HTTP logging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you need to add HTTP logging service into the IoC container&lt;/li&gt;
&lt;li&gt;you need to use the built-in middleware of UseHttpLogging() to enable automatic logging of HTTP requests and responses in your application
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, HTTPLogging doesn't log information about the request body and response body. You can set the configuration to capture request and response body but that is not recommended because if you log every incoming request body and response body it will overhead and slow down your server performance. Only log body if in an extremely needed situation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Serilog
&lt;/h2&gt;

&lt;p&gt;In this post, i will show you my favorite log framework,  serilog. Why serilog is a good choice then built-in logging ASP.NET? Because they offer more sinks (sink in serilog refers to log destination). You can print the log event into a file, database (SQL Server, MySQL, etc), Seq, Azure, and have more powerful structured logging.&lt;/p&gt;

&lt;p&gt;after that you can configure in program file&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjwwbz1tjr0k01zs9yhy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjwwbz1tjr0k01zs9yhy.png" alt="Serilog sinks" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to utilize serilog in ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;First, you need to install Serilog and Serilog.AspNetCore from nugget package. In this post, i will show you how to send a log event into 3 sinks which are console, file, and Seq. So you need to install the respective serilog sinks (Serilog.Sinks.Console, Serilog.Sinks.File, and Serilog.Sinks.Seq)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6eszqnp2xkadyd3v2296.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6eszqnp2xkadyd3v2296.png" alt="serilog sink packages" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Seq
&lt;/h2&gt;

&lt;p&gt;If you don't know Seq, Seq is a hosted monitoring tool for easy search and analysis in realtime for structured log. Here is the link to how to download and set seq tool on your machine &lt;a href="https://docs.datalust.co/docs/getting-started" rel="noopener noreferrer"&gt;https://docs.datalust.co/docs/getting-started&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To set Serilog as logging provider add following code into &lt;code&gt;Program&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
above code tell serilog to read its configuration is loaded from configuration file such as &lt;code&gt;appsetting.json&lt;/code&gt; and read services in IoC container and make available to serilog. 

&lt;p&gt;here how to set serilog configuration&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
&lt;code&gt;Using&lt;/code&gt; section to determine which sinks to include, and then it uses those sinks for logging


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Each sink has its configuration you can configure it in &lt;code&gt;WriteTo&lt;/code&gt; section, for every sink need a &lt;code&gt;Name&lt;/code&gt;property. For Seq you need to Supply &lt;code&gt;serverUrl&lt;/code&gt; which locates the URL of the Seq server in the &lt;code&gt;Args&lt;/code&gt; section and for the file sink you need to supply a &lt;code&gt;path&lt;/code&gt; to find where the file will be created for the first time and append the log message if the file already exists, in addition, you can add more configuration such as &lt;code&gt;rollingInterval&lt;/code&gt; to determines how frequently new log file will be created based on the specified time interval, &lt;code&gt;fileSizeLimitBytes&lt;/code&gt; to limit the maximum size of the log file and &lt;code&gt;rollOnFileSizeLimit&lt;/code&gt; set to true to create a new file every time the size of log file reaches maximum limit.

&lt;p&gt;console serilog looks like&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fid988o7h0te4db77gv8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fid988o7h0te4db77gv8g.png" alt="serilog console" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;file serilog looks like&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F474q5aejjzzri7uduir7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F474q5aejjzzri7uduir7.png" alt="serilog file" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;seq serilog looks like&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmyl3hc2wrjraawu7q2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmyl3hc2wrjraawu7q2b.png" alt="serilog seq" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
Here is one of the benefits use of a structured log instead of a static message log, You can search by property of log-structured event context like below&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fameq5f91yhlaptjvb7gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fameq5f91yhlaptjvb7gy.png" alt="Search by property context" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Enricher
&lt;/h2&gt;

&lt;p&gt;An enricher is additional information or context like machine name, environment’s user name, and other custom user-defined information that will attach to your log event. It enriches information so it will help make it easier to debug and analyze. Enricher will add key-value pairs to your logs.&lt;/p&gt;

&lt;p&gt;If you wanna add context that is true for all log events you can add static global key-value pairs by adding &lt;code&gt;Properties&lt;/code&gt; to &lt;code&gt;appsettings.json&lt;/code&gt; and adding key-value pair as nested property&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

&lt;p&gt;You can add dynamic value into context with the help of the Diagnostic Context mechanism,  there are 2 main types which are LogContext and IDiagnosticContext. &lt;br&gt;
Note: for both dynamic contexts you need to supply &lt;code&gt;LogContext&lt;/code&gt; as a value in the &lt;code&gt;Enrich&lt;/code&gt;section.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;LogContext&lt;/strong&gt;&lt;br&gt;
Dynamically add properties to log events for a specific block code by executing &lt;code&gt;LogContext.PushProperty()&lt;/code&gt; static method inside using statement. But first, you need to install Serilog.Enrichers.Context package from nugget package manager&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
context will be attached only for log event that inside using block of &lt;code&gt;LogContext.PushProperty()&lt;/code&gt;

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

&lt;p&gt;&lt;strong&gt;IDiagnosticContext&lt;/strong&gt;&lt;br&gt;
Dynamic context that only appears in the completion request response of the log event. But first, you need to configure Serilog’s request logging middleware which is &lt;code&gt;app.UseSerilogRequestLogging()&lt;/code&gt;.Unlike &lt;code&gt;useHttpLogging&lt;/code&gt; which logs HTTP requests and responses in several events, serilog’s request logging only logs a single event at the completion of the HTTP request response.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;First, you need to inject IDiagnosticContext instance then you can set the context to completion of the HTTP request-response with &lt;code&gt;Set&lt;/code&gt; IDianosticContext instance's method.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


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

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

&lt;p&gt;Logging is vital for every application. Especially for big and complex applications. You can perform identity and analysis behavior of your application in production hence you can easily find the root of the problem if there is a bug or unintended behavior in your application easily and quickly, it is also used as a performance monitor because it logs the response time of request so if there is something that taking a long time you as a developer can optimize it, so it is recommended that you always use logging system each time you develop a new application&lt;/p&gt;

</description>
      <category>logging</category>
      <category>aspdotnet</category>
    </item>
    <item>
      <title>Understanding Model Binding in ASP.NET</title>
      <dc:creator>Panji Kristi Prawiro</dc:creator>
      <pubDate>Thu, 29 Aug 2024 12:53:25 +0000</pubDate>
      <link>https://dev.to/prawiropanji/understanding-model-binding-in-aspnet-m0</link>
      <guid>https://dev.to/prawiropanji/understanding-model-binding-in-aspnet-m0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;HTTP is the backbone of a website's communication. This regulates how clients and servers exchange information. One of the must-have capabilities of a server is to get data from a client's request. In ASP NET Core, every incoming request from the client will be caught by the Kestrel server and transformed into object context, then passed into source code, and finally routed to the endpoint. First, let's look at how to get data from request object context without a model binding mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get query string from context object&lt;/strong&gt;&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%2Fv4mtt8isymhaikn65uwz.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%2Fv4mtt8isymhaikn65uwz.png" alt="Send request with query string"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&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%2Fzf0022mjoiyv0wpve6bz.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%2Fzf0022mjoiyv0wpve6bz.png" alt="Watch extracted query strings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without model binding, you must do extra work to do. First, you need to access the &lt;code&gt;IQueryCollection&lt;/code&gt; object from &lt;code&gt;HttpContext&lt;/code&gt; and check if there is any associate key-value pair. If any, it will give you a &lt;code&gt;StringValues&lt;/code&gt; type, which under the hood implements &lt;code&gt;IList&amp;lt;string&amp;gt;&lt;/code&gt; so you need to access a string element from that list, and then you need to perform a type conversation from the string into the appropriate value. This tedious work increases the error-proneness, luckily ASP.NET offers the easy way with &lt;strong&gt;Model Binding&lt;/strong&gt; mechanism. &lt;/p&gt;

&lt;h2&gt;
  
  
  Model Binding
&lt;/h2&gt;

&lt;p&gt;Model binding is one of the greatest mechanisms in ASP.NET. It is a process of collecting the data from an incoming request &lt;em&gt;(it could be in the form of &lt;strong&gt;query string&lt;/strong&gt;, &lt;strong&gt;route data&lt;/strong&gt;, &lt;strong&gt;request body&lt;/strong&gt;, or &lt;strong&gt;request header&lt;/strong&gt;)&lt;/em&gt; and then supplying the values as an action method argument. Hence, you have access directly to data that was sent from the client to perform validation and process it in the business logic layer. Behind the scenes, ASP.NET will take care of the binding process, so it's not ours. The model binding mechanism will automatically perform when requests are routed to match endpoints and right before the execution of the action method.&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%2Fdpo6rk7pkm2k3fqcvz5i.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%2Fdpo6rk7pkm2k3fqcvz5i.png" alt="Model Binding Mechanism Illustration perform between incoming request and execution of action method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;let's look how to get query string data with model binding&lt;/strong&gt;&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%2Fv4mtt8isymhaikn65uwz.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%2Fv4mtt8isymhaikn65uwz.png" alt="Send request with query string"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&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%2F3j0e2httjk87gg750870.png" alt="Watch value of variable"&gt;

&lt;blockquote&gt;
&lt;p&gt;It seems like magic 🎩✨🐇 isn't it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is significantly quicker and easier. to extract data from a query with model binding that you wouldn't need to perform a data conversation from a string into an appropriate type. It comes automatically behind the scenes by model binding.&lt;/p&gt;

&lt;p&gt;In order to bind successfully, you must make sure the name of the key of the query string matches the identifier of the action method parameter. but you don't have to match the case because it is not case-sensitive. Bonded data is not limited to one source. It still works fine if you place the data in the query string and route data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get Query String and Route Data with model binding&lt;/strong&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%2Fsivtms0t87ncgrnz7fri.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%2Fsivtms0t87ncgrnz7fri.png" alt="postman send request with query string and route data"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&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%2F3j0e2httjk87gg750870.png" alt="Watch value of variable"&gt;

&lt;p&gt;So it is great that ASP.NET has these features to make development more intuitive, easy, and fast. However, if you don't understand the behavior of model binding, you will end up confused. Let's say the client makes the following request: &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%2Fitftp6i2p5tdfzrl4eww.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%2Fitftp6i2p5tdfzrl4eww.png" alt="Send Request with route data and query string "&gt;&lt;/a&gt;&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%2F3j0e2httjk87gg750870.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%2F3j0e2httjk87gg750870.png" alt="Watch value of variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From above, we can see that it has collision data between the query string and route data because they have the same identifier called "&lt;em&gt;movieId&lt;/em&gt;". If we look at the above watch window, the movieId gets populated with a value of 89. You might wonder why ASP.NET extracts "&lt;em&gt;movieId&lt;/em&gt;" parameter data from route data instead of a query string? It turns out ASP.NET has an order of priority for model binding. Let's take a look at the image below, It starts from the top, which has the highest priority, down to the bottom, which has less priority.&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%2Flbtnwu1rb6dr1q5z1r2t.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%2Flbtnwu1rb6dr1q5z1r2t.png" alt="Model binding priority"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great, now you have a better understanding of model binding behavior.&lt;br&gt;
But what if you don't want to achieve this behavior?&lt;br&gt;
You can use the &lt;code&gt;[FromQuery]&lt;/code&gt; attribute to tell ASP.NET, &lt;em&gt;"Hey, forget about your order priority. I will state explicitly that I want you to bind the data from the query string instead."&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&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%2F55kyce9818wow99wg83y.png" alt="watch variable value"&gt;&lt;br&gt;
It will populated movieId with value of 22 instead of 89.

&lt;p&gt;here another useful attribute list that you can use to explicitly specify the source of data for action method parameters&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[FromRoute]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[FromQuery]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[FromBody]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[FromForm]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Model Binding with Model Class
&lt;/h2&gt;

&lt;p&gt;What happens if the customer provides a lot of data? Of course, you don't want to scatter up the action method arguments; it will clutter your code. Instead,  you can create a model class and declare it as an action method parameter. Model binding will automatically map incoming request data to the properties of your model class based on their names.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;client send a request with a &lt;code&gt;multipart/form-data&lt;/code&gt; content type&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%2F2h0gkf016aldro9gt07c.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%2F2h0gkf016aldro9gt07c.png" alt="send request upload movie"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&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%2Fidsruaqvpw0gcn21n7k7.png" alt="watch movie property value"&gt;

&lt;p&gt;Great, the movie object has been automatically populated based on the data from the request form-data. Sometimes you want more granular control over which properties get populated from incoming request data, to achieve this, you can utilize &lt;code&gt;[Bind]&lt;/code&gt; and &lt;code&gt;[BindNever]&lt;/code&gt;attributes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bind&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

decorate action method parameter with Bind attribute then you need to supply name of property or parameter to include in binding. It will tell that we only interest to populate &lt;code&gt;Title&lt;/code&gt; value and leave the rest of properties to hold null or default value&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;BindNever&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

decorate the property model that you want to exclude from the model binding process. It will make the &lt;code&gt;Title&lt;/code&gt; property excluded from the binding process hence, it will store a null value, and the rest of the properties still be populated from the binding.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Custom Model Binders
&lt;/h2&gt;

&lt;p&gt;ASP.NET gives you more control over the binding process from requests into action method parameters by creating your own model binding class. so it will override the built-in Model binding mechanism and use your own model binding class. Let's say that the client will send query string data of poster URL and trailer URL and you want to store them into a single value separated by semicolon. First, you need to create a class that implements the &lt;code&gt;IModelBinder&lt;/code&gt; interface and overrides the &lt;code&gt;BindModelAsync&lt;/code&gt; method.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After you create your own model binder class, you need to decorate the parameter of your model parameter in the action method with the &lt;code&gt;ModelBinder&lt;/code&gt; attribute and pass your model as a type on the first argument.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&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%2Fsa5lbmlc7upv5md7v0x0.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%2Fsa5lbmlc7upv5md7v0x0.png" alt="send request with posterUrl and trailerUrl data"&gt;&lt;/a&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%2Fbfrode4y76qmju3aeirp.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%2Fbfrode4y76qmju3aeirp.png" alt="Watch window value of movie with custom model binder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are successfully using your own custom model binder so you can have granular control over the rule of the binding process. &lt;/p&gt;

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

&lt;p&gt;Model Binding Mechanism in ASP.NET helps us to populate data from requests with a breeze. It will perform automatically, and you don't have to write tedious code that could be error-prone. With the understanding behavior of model binding performed by ASP.NET you know how to handle it if something looks off or does not look as you expect it with the right technique. Even if the model binding by ASP.NET cannot meet your requirements, you can create your custom model binders by yourself and override the built-in model binding mechanism in ASP.NET.&lt;/p&gt;

</description>
      <category>aspnet</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
