# 10.1: Add Service Method and DTOs

## Add IMessageService

In your `.Contracts` project, add a new interface called `IMessageService.cs`:

```csharp
public interface IMessageService
{
    Task<Message> GetMessage(int id);
    Task<PagedList<MessageToReturn>> GetMessagesForUser();
    Task<IEnumerable<MessageToReturn>> GetMessageThread(int userId, int recipientId);
    Task<MessageToReturn> CreateMessage(MessageForCreation messageForCreation);
    Task<bool> SaveAll();
}
```

## GetMessage() Method

In your `.Services` project, add a new class called `MessageService.cs`.

Inherit from `IMessageService`, `ctrl + .` and choose `Implement interface`.

For now, we'll just implement the `GetMessage()` and the `SaveAll()` methods. The `CreateMessage()` is much longer and we'll add that after.

```csharp
public class MessageService : IMessageService
{
    private readonly EFConnectContext _context;
    private readonly IUserService _userService;

    public MessageService(EFConnectContext context, IUserService userService)
    {
        _context = context;
        _userService = userService;
    }

    public async Task<Message> GetMessage(int id)
    {
        return await _context.Messages
                        .FirstOrDefaultAsync(m => m.Id == id);
    }

    public Task<PagedList<MessageToReturn>> GetMessagesForUser()
    {
        throw new System.NotImplementedException();
    }

    public Task<IEnumerable<MessageToReturn>> GetMessageThread(int userId, int recipientId)
    {
        throw new System.NotImplementedException();
    }

    public Task<IEnumerable<MessageToReturn>> CreateMessage(MessageForCreation messageForCreation)
    {
        throw new System.NotImplementedException();
    }

    public async Task<bool> SaveAll()
    {
        return await _context.SaveChangesAsync() > 0;
    }
}
```

## Register MessageService

Now, let's register our new service for dependency injection in the `Startup.cs` file in the `.API` project:

```csharp
services.AddScoped<IMessageService, MessageService>();
```

## Add MessageForCreation DTO

In the `.Models` project, add a new folder called `Message`. Inside of that folder, add a new class called `MessageForCreation.cs`:

```csharp
public class MessageForCreation
{
    public int SenderId { get; set; }
    public int RecipientId { get; set; }
    public DateTime DateSent { get; set; }
    public string Content { get; set; }

    public MessageForCreation()
    {
        DateSent = DateTime.Now;
    }
}
```

## Add MessageToReturn DTO

Next, we'll also add a `MessageToReturn` DTO in the same folder:

```csharp
public class MessageToReturn
{
    public int Id { get; set; }
    public int SenderId { get; set; }
    public string SenderKnownAs { get; set; }
    public string SenderPhotoUrl { get; set; }
    public int RecipientId { get; set;}
    public string RecipientKnownAs { get; set; }
    public string RecipientPhotoUrl { get; set; }
    public string Content { get; set; }
    public bool IsRead { get; set; }
    public DateTime? DateRead { get; set; }
    public DateTime DateSent { get; set; }
}
```

## CreateMessage() Method

Now that we have the DTOs, we can implement the `CreateMessage` method in our `MessageService`:

```csharp
public async Task<MessageToReturn> CreateMessage(MessageForCreation messageForCreation)
{
    var sender = await _userService.GetUser(messageForCreation.SenderId);
    var recipient = await _userService.GetUser(messageForCreation.RecipientId);

    var message = new Message
    {
        SenderId = messageForCreation.SenderId,
        RecipientId = messageForCreation.RecipientId,
        DateSent = messageForCreation.DateSent,
        Content = messageForCreation.Content,
        IsRead = false,
        SenderDeleted = false,
        RecipientDeleted = false
    };

    _context.Add(message);

    if (!await SaveAll())
        return null;

    return new MessageToReturn
    {
        Id = message.Id,
        SenderId = message.SenderId,
        SenderKnownAs = message.Sender.KnownAs,
        SenderPhotoUrl = message.Sender.Photos.FirstOrDefault(p => p.IsMain).Url,
        RecipientId = message.RecipientId,
        RecipientKnownAs = message.Recipient.KnownAs,
        RecipientPhotoUrl = message.Recipient.Photos.FirstOrDefault(p => p.IsMain).Url,
        Content = message.Content,
        IsRead = message.IsRead,
        DateRead = message.DateRead,
        DateSent = message.DateSent
    };
}
```

We're getting the recipient and sender `User`s based off the `Id` in the `MessageForCreation` with our `UserService`.

Then we're mapping the `MessageForCreation` to a new `Message` entity for us to save to the database.

Then we're returning *another* mapping - this time from `Message` to `MessageToReturn`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://eleven-fifty-academy.gitbook.io/dotnet-302-core/10-messaging/10.1-add-service-method-and-dtos.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
