<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <title>ABP.IO Stories</title>
    <link>https://abp.io/community/articles</link>
    <description>A hub for ABP Framework, .NET, and software development. Access articles, tutorials, news, and contribute to the ABP community.</description>
    <lastBuildDate>Tue, 06 Oct 2026 03:40:25 Z</lastBuildDate>
    <generator>Community - ABP.IO</generator>
    <image>
      <url>https://abp.io/assets/favicon.ico/favicon-32x32.png</url>
      <title>ABP.IO Stories</title>
      <link>https://abp.io/community/articles</link>
    </image>
    <a10:link rel="self" type="application/rss+xml" title="self" href="https://abp.io/community/rss?member=Enes" />
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/what-is-object-to-object-mapping-0hntytz4</guid>
      <link>https://abp.io/community/posts/what-is-object-to-object-mapping-0hntytz4</link>
      <a10:author>
        <a10:name>Enes</a10:name>
        <a10:uri>https://abp.io/community/members/Enes</a10:uri>
      </a10:author>
      <category>object-mapping</category>
      <category>automapper</category>
      <title>What is Object to Object Mapping?</title>
      <description>In this article, you will learn about object-to-object mapping and the automapper library that automates it.</description>
      <pubDate>Tue, 21 May 2024 06:54:43 Z</pubDate>
      <a10:updated>2026-10-06T01:23:20Z</a10:updated>
      <content:encoded><![CDATA[<h1>What is Object to Object Mapping?</h1>
<p>Mapping the properties of one object to the properties of another object is called <strong>Object to Object Mapping</strong>. Most of the time, you don't want to show the data you store in your database to end users as it is. Instead, you only return users the information they need for that operation and reduce the output size.</p>
<p>For example, in database tables that contain relationships, we analyze the relationships and present meaningful data to users. Suppose we have a product and a category object, we keep a property called <code>categoryId</code> in the <code>Product</code> entity. However, it would be illogical to show the <code>categoryId </code> property to users. Therefore, we can create a DTO (data transfer object) and show the <strong>category name</strong>  to the end users, instead of the <code>categoryId</code> directly.</p>
<p>DTOs are used to transfer data of objects from one object to another one. We often need to map our entities to DTOs and DTOs to entities. For example, consider the code below:</p>
<pre><code class="language-csharp">    public virtual async Task&lt;CustomerDto&gt; CreateAsync(CustomerCreateDto input)
    {

        var customer = await _customerManager.CreateAsync(
        input.BirthDay, input.MembershipDate, input.FirstName, input.LastName
        );
        CustomerDto customerDto = new CustomerDto
        {
            Id = customer.Id,
            FirstName = input.FirstName,
            LastName = input.LastName,
            // ...other
        };
        
        return customerDto;
    }

</code></pre>
<p>As can be seen here, it's repetitive and tedious to manually map an object to another similar object. Also, it violates the <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY principle</a>, makes your code more complicated and reduces readability. Instead of manually mapping objects, you can use the  <a href="https://automapper.org/">AutoMapper</a> library to automatically map two objects' properties:</p>
<pre><code class="language-csharp">        public virtual async Task&lt;CustomerDto&gt; CreateAsync(CustomerCreateDto input)
        {

            var customer = await _customerManager.CreateAsync(
            input.BirthDay, input.MembershipDate, input.FirstName, input.LastName
            );

            return ObjectMapper.Map&lt;Customer, CustomerDto&gt;(customer);
        }
</code></pre>
<p>The <strong>ObjectMapper.Map</strong> method allows you to convert your <code>Customer</code> entity to <code>CustomerDto</code>. <code>IObjectMapper</code> interface is a service, that comes from the <strong>AutoMapper</strong> library, so let's learn more about <strong>AutoMapper</strong> in the next section.</p>
<h1>What is AutoMapper?</h1>
<p>Automapper is a .NET library that automates object-to-object mapping. ABP provides abstractions for object-to-object mapping and has an integration package to use <a href="http://automapper.org/">AutoMapper</a> as the object mapper.</p>
<p>Automapper is a library that transforms similar objects into each other. We can imagine Automapper as a machine that transforms an apple with a hat into an apple without a hat:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/automapper.png" alt="AutoMapper" /></p>
<p>In this chapter, I will show you how to use the AutoMapper library in an ABP-based application. For this reason, I assume that you already have an ABP-based application created. If you have not yet created an ABP-based application, please follow the <a href="https://docs.abp.io/en/abp/latest/Getting-Started-Create-Solution?UI=MVC&amp;DB=EF&amp;Tiered=No">Getting Started documentation</a>.</p>
<p>Create a domain entity similar to this one:</p>
<pre><code class="language-csharp">    public class Customer : FullAuditedAggregateRoot&lt;Guid&gt;
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public DateTime BirthDay { get; set; }
        public DateTime MembershipDate { get; set; }
    }
</code></pre>
<p><code>Customer</code> entity contains some properties (such as <code>FirstName</code>, <code>LastName</code>, ... and other audited properties coming from the base class - <code>DeleterId</code>, <code>IsDeleted</code>, <code>CreationTime</code> etc. -). Typically, you would not want to show/return all of these properties to end users, at that point, you can create a DTO class and only define the properties that you want to return to the end users.</p>
<p>Let's create the <code>CustomerGetDto</code> class in the <code>*.Application.Contracts</code> project as follows:</p>
<pre><code class="language-csharp">    public class CustomerGetDto
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public DateTime BirthDay { get; set; }
    }
</code></pre>
<p>After creating our entity and output DTO classes, now in the application service implementation, we can return the <code>CustomerGetDto</code> class, as a result of listing the customers. For that reason, we can write a code as follows:</p>
<pre><code class="language-csharp">public virtual async Task&lt;PagedResultDto&lt;CustomerGetDto&gt;&gt; GetListAsync(GetCustomersInput input)
 {
     var totalCount = await _customerRepository.GetCountAsync(input.FilterText, input.FirstName, input.LastName, input.BirthDayMin, input.BirthDayMax, input.MembershipDateMin, input.MembershipDateMax);
     var items = await _customerRepository.GetListAsync(input.FilterText, input.FirstName, input.LastName, input.BirthDayMin, input.BirthDayMax, input.MembershipDateMin, input.MembershipDateMax, input.Sorting, input.MaxResultCount, input.SkipCount);

     return new PagedResultDto&lt;CustomerGetDto&gt;
     {
         TotalCount = totalCount,
         Items = ObjectMapper.Map&lt;List&lt;Customer&gt;, List&lt;CustomerGetDto&gt;&gt;(items)
     };
 }
</code></pre>
<p>In this code, we first get the total number of our customers and all customers according to the specified filters, then we map <code>List&lt;Customer&gt;</code> to <code>List&lt;CustomerGetDto&gt;</code> using the <code>ObjectMapper.Map</code> method from the <strong>ApplicationService</strong> base class. This way we have full control over which properties are returned to the end users.</p>
<p>After mapping the <code>Customer</code> entity to the <code>CustomerGetDto</code> class. Before running our application, we should define the mappings in the <code>*AutoMapperProfile</code> class in the <code>*.Application</code> project as follows:</p>
<pre><code class="language-csharp">public class YourApplicationAutoMapperProfile : Profile
{
    public YourApplicationAutoMapperProfile()
    {
        CreateMap&lt;Customer, CustomerGetDto&gt;();
    }
}
</code></pre>
<p>Finally, we can run our application and navigate to the <strong>/swagger</strong> endpoint to try our endpoint. When we send a request, we should get the result as follows:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/swagger1.png" alt="Swagger" /></p>
<h2>Advanced: Mapping Configurations</h2>
<p>In some scenarios, you may want to make some customizations when mapping two objects. For example, let's assume that you want to create the <code>CustomerGetDto</code> class as follows:</p>
<pre><code class="language-csharp">  public class CustomerGetDto
  {
      public string? FullName { get; set; }
      public int Age { get; set; }
  }
</code></pre>
<p>AutoMapper can't map these properties automatically, because they do not exist in the source object, which is the <code>Customer</code> entity. Therefore, you need to specify the exception and update your <code>YourApplicationAutoMapperProfile</code> class as follows:</p>
<pre><code class="language-csharp">
CreateMap&lt;Customer, CustomerGetDto&gt;().ForMember(c=&gt;c.FullName,opt=&gt; opt.MapFrom(src =&gt; src.FirstName + &quot; &quot; + src.LastName))
    .ForMember(c=&gt;c.Age, opt=&gt; opt.MapFrom(src=&gt; DateTime.UtcNow.Year -src.BirthDay.Year));

</code></pre>
<p>This configuration concatenates and matches <strong>FirstName</strong> and <strong>LastName</strong> properties into the <strong>FullName</strong> property and subtracts <strong>BirthDate</strong> from today's year and assigns it to the customer's <strong>Age</strong>.
After these configurations, if you make a request to the relevant endpoint, the output will look like:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/swagger2.png" alt="Swagger" /></p>
<p>For more information on object-to-object mapping with <a href="https://abp.io/">ABP Framework</a>, see the <a href="https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping">documentation</a>.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a12ac1b-2755-e860-02a0-a9b1ab945b8b" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a12ac1b-2755-e860-02a0-a9b1ab945b8b" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/using-fluentvalidation-with-abp-framework-2cxuwl70</guid>
      <link>https://abp.io/community/posts/using-fluentvalidation-with-abp-framework-2cxuwl70</link>
      <a10:author>
        <a10:name>Enes</a10:name>
        <a10:uri>https://abp.io/community/members/Enes</a10:uri>
      </a10:author>
      <category>validation</category>
      <category>fluent-validation</category>
      <title>Using FluentValidation with ABP Framework</title>
      <description>This article can help you understand the use of Fluent validation within the ABP Framework.</description>
      <pubDate>Wed, 08 May 2024 12:28:36 Z</pubDate>
      <a10:updated>2026-10-06T01:27:55Z</a10:updated>
      <content:encoded><![CDATA[<h1>Using FluentValidation with ABP Framework</h1>
<h2>What is Validation? Why Do We Need to Validate?</h2>
<p>Validation is checking whether data is valid or not. We can liken validations to the cell membrane of our application. Just as the cell does not want to let in harmful substances, we do not want to add erroneous data to the database, which is critical to our application. Validations allow data that follows the rules to reach the database. Data that does not comply with the rules will not access the database at all, and the operation will fail.</p>
<p><img src="https://raw.githubusercontent.com/EnesDONER/abp/dev/docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/validation.png" alt="Validation" /></p>
<p>Validations make your application run more efficiently as they are not directly tied to the database. They should be implemented across various layers of the application, including the UI, backend, and database, to prevent malicious users from bypassing these checks. Fluent validation is frequently employed for creating backend validations.</p>
<h2>What is Fluent Validation?</h2>
<p>Fluent validation is a library for checking whether data is valid or not. Fluent validation can be applied to your code in a fluent and understandable way.</p>
<h2>Why We Should Use Fluent Validation?</h2>
<p>Fluent Validation allows you to define your validation rules in a clear and flexible way. This means you can comfortably handle complex validation scenarios in your code. This makes your development process much more manageable. The readability that Fluent Validation offers really makes things easier. Having a clear understanding of what your validation rules do is a huge advantage when working on your code. In short, your code is cleaner and clearer. Fluent Validation is also very functional in terms of testability. By defining your validation rules in separate classes, you can easily test and maintain these rules. Fluent Validation is a widely used validation library on the .NET platform. As such, it has become a common standard among .NET developers. This provides advantages in terms of community support and compatibility. So, using Fluent Validation simplifies your development process by making your code more understandable, manageable and testable.</p>
<p>In this section, I will show you how to use FluentValidation library within an ABP-based application. Therefore, I assume that you have an ABP-based application that has already been created. If you haven't created an ABP-based application yet, please follow the <a href="https://docs.abp.io/en/abp/latest/Getting-Started-Create-Solution?UI=MVC&amp;DB=EF&amp;Tiered=No">Getting Started documentation</a>.</p>
<p>Using Fluent validation with Abp is quite simple. Open a command line window in the folder of the project (.csproj file) and type the following command:</p>
<pre><code class="language-bash">abp add-package Volo.Abp.FluentValidation
</code></pre>
<p>If you have not created your abp project, review the <a href="https://docs.abp.io/en/abp/latest/Tutorials/Todo/Overall">steps to create</a> it now.</p>
<p>Create the <code>Product</code> entity as below:</p>
<pre><code class="language-csharp">  public class Product: FullAuditedAggregateRoot&lt;Guid&gt;
   {
       public string Name { get; set; } = string.Empty;
       public decimal Price { get; set; }
       public int Stock { get; set; }
       public string? LicenseKey { get; set; }
    }
</code></pre>
<p>You must have ProductCreateDto :</p>
<pre><code class="language-csharp">      public class ProductCreateDto
    {
        public string Name { get; set; } 
        public decimal Price { get; set; }
        public int Stock { get; set; }
        public string? LicenseKey { get; set; }
     }
</code></pre>
<p>Create the <code>ProductCreateDtoValidator</code> class in the <strong>Products</strong> folder in the <code>Application.Contracts</code> project:</p>
<pre><code class="language-csharp">  public class ProductCreateDtoValidator :AbstractValidator&lt;ProductCreateDto&gt;
{
    public ProductCreateDtoValidator()
    {
        RuleFor(p=&gt;p.Name).
          NotEmpty().
            WithMessage(&quot;Product name cannot be empty&quot;);
        
        RuleFor(p=&gt;p.Name).
            MinimumLength(3).
            MaximumLength(100).
            WithMessage(&quot;Product name must be between 3 and 100 characters&quot;);

        RuleFor(p =&gt; p.Stock).
            GreaterThanOrEqualTo(0).
            WithMessage(&quot;Product stock should not be negative&quot;);

        RuleFor(p =&gt; p.Price).
           GreaterThanOrEqualTo(0).
           WithMessage(&quot;Product Price should not be negative&quot;);
    }
}
</code></pre>
<p>The validator class you create should inherit from <code>AbstractValidator</code>.  You should give <code>AbstractValidator</code> the class you want to validate generically. You have to create a constructor method. You must write the code in this constructor method. Fluent validation provides you with ready-made methods that you can use to write validations very easily.</p>
<p>The <strong>RuleFor</strong> method allows you to write a validation rule. You must specify in the parameter for which property you want to write a validation rule.</p>
<p>With the <strong>NotEmpty</strong> method you can specify that a property cannot be null.</p>
<p>With <strong>MinimumLength</strong> and <strong>MaximumLength</strong> you can specify the minimum and maximum number of characters the property can take.</p>
<p>With the <strong>GreaterThanOrEqualTo</strong> method you can specify that the value of the property must be greater than or equal to the value entered as a parameter.</p>
<p><strong>WithMessage</strong> method you can specify the message to be sent when the validation fails.</p>
<p>You can add a method to write your own customized validation code. For example, let's write the code that requires the license key field to contain the word “key”.</p>
<pre><code class="language-csharp">  private bool ContainsKey(string arg)
  {
      return arg.IndexOf(&quot;key&quot;, StringComparison.OrdinalIgnoreCase) &gt;= 0;
  }
</code></pre>
<p>Add the code to the constructor to use this method:</p>
<pre><code class="language-csharp">RuleFor(p =&gt; p.LicenseKey).
	Must(ContainsKey).
	WithMessage(&quot;Product license key must contain the word 'key'&quot;);
	
</code></pre>
<p>Try to add data that does not meet the validation rules</p>
<p><img src="https://raw.githubusercontent.com/EnesDONER/abp/dev/docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/adding-incorrect-data.png" alt="Adding Incorrect Data" /></p>
<p>If one of the validation rules does not meet the rules, then the following error will be received for the custom rule that we defined:</p>
<p><img src="https://raw.githubusercontent.com/EnesDONER/abp/dev/docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/error.png" alt="Error" /></p>
<p>For more information on fluent validation with abp framework, see the <a href="https://docs.abp.io/en/abp/latest/FluentValidation">documentation</a></p>
<p>For more information on fluent validation, see the <a href="https://docs.fluentvalidation.net/en/latest/">documentation</a></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a126a5a-2cc5-398e-66c1-edaabeeb99d2" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a126a5a-2cc5-398e-66c1-edaabeeb99d2" medium="image" />
    </item>
  </channel>
</rss>