Git Product home page Git Product logo

hands-on-domain-driven-design-with-.net-core's Introduction

Hands-On Domain-Driven Design with .NET Core

Hands-On Domain-Driven Design with .NET Core

This is the code repository for Hands-On Domain-Driven Design with .NET Core, published by Packt.

Tackling complexity in the heart of software by putting DDD principles into practice

What is this book about?

Developers across the world are rapidly adopting DDD principles to deliver powerful results when writing software that deals with complex business requirements. This book will guide you in involving business stakeholders when choosing the software you are planning to build for them. By figuring out the temporal nature of behavior-driven domain models, you will be able to build leaner, more agile, and modular systems.

This book covers the following exciting features:

  • Discover and resolve domain complexity together with business stakeholders
  • Avoid common pitfalls when creating the domain model
  • Study the concept of Bounded Context and aggregate
  • Design and build temporal models based on behavior and not only data
  • Explore benefits and drawbacks of Event Sourcing Get acquainted with CQRS and to-the-point read models with projections Practice building one-way flow UI with Vue.js Understand how a task-based UI conforms to DDD principles

If you feel this book is for you, get your copy today!

https://www.packtpub.com/

Instructions and Navigations

All of the code is organized into folders. For example, Chapter02.

The code will look like the following:

protected async Task UsingSession(
    Func<IAsyncDocumentSession, Task> operation

Following is what you need for this book: This book is for .NET developers who have an intermediate level understanding of C#, and for those who seek to deliver value, not just write code. Intermediate level of competence in JavaScript will be helpful to follow the UI chapters.

With the following software and hardware list you can run all code files present in the book (Chapter 5-11, 13).

Software and Hardware List

No. Software required OS required
1 JetBrains Rider 2019.1 or higher Windows, Linux, macOS
2 Microsoft Visual Studio Windows, Linux, macOS
3 Docker 18.09.2 or higher Windows, Linux, macOS
4 .NET Core SDK 2.2.203 or higher Windows, Linux, macOS
5 EventStore Windows, Linux, macOS
6 PostgreSQL Windows, Linux, macOS
7 RavenDB Windows, Linux, macOS

We also provide a PDF file that has color images of the screenshots/diagrams used in this book. Click here to download it.

Errata

Page 19 (Paragraph 1, line 5): At the other hand should be On the other hand
Page 152 (Paragraph 1, line 4): That's we call this layer should be That's why we call this layer
Page 32 (Paragraph 5, line 32): silly in front of the bund of nerds should be silly in front of the bunch of nerds

Related products

Get to Know the Author

Alexey Zimarev is a software architect with a present focus on domain models, Domain-Driven Design (DDD), event sourcing, message-driven systems and microservices, coaching, and mentoring. Alexey is also a contributor to several open source projects, such as RestSharp, Proto.Actor and MassTransit, and is the organizer of the DDD Norway meetup. Check Alexey's blog and reach out in Twitter @Zimareff.

Suggestions and Feedback

Open an issue in this repository for bug reports, feedback, suggestions and ideas.

Download a free PDF

If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.

https://packt.link/free-ebook/9781788834094

hands-on-domain-driven-design-with-.net-core's People

Contributors

abhij991985 avatar alexeyzimarev avatar christos-p avatar gaurav-packt avatar moientajik avatar packt-itservice avatar packtutkarshr avatar rohitpackt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hands-on-domain-driven-design-with-.net-core's Issues

PostgreSql issue in Chapter 8

Hi,

In chapter 8, regarding the creation of a postgresql database, when I use the cmd and the "docker-compose up" command, I take this message:
" invalid mount config for type "bind": bind source path does not exist: c:...\marketplace\init.sql".
But my init.sql exists in this specific path and contains all the required information.
Do you have any idea why this happen?

Thanks.

Possible projection corruption?

I'm still new to EventStore so maybe I'm missing something about the catchup subscription... but in the subscription manager, the projection stores and the checkpoint store aren't transactional so if a crash occurs right after projection handlers complete but before the checkpoint store completes, wouldn't you get double processing in the projections the next time the application restarts?

Versioning Events

Today i was wondering, how event versioning would actually be implemented in your ClassifiedAd-Example.

In Chapter 13 you introduced the TypeMapper which is used in EventMappings.cs.

But then when storing events to the EventStore, the EventData is filled with two information about the original event object:

  1. The mapped type name
  2. The CLR-Type in the Metadata-Object

When loading events from the store, only the TypeMapper is consulted in order to find the correct type to deserialize the event json. So i assume the CLR-Type-Information is just a leftover from the previous chapters.

But what boggles me now: Since the version information of the concrete event classes is now "hidden" behind a nice name for the EventType, how would you solve Event-Versioning in this scenario?

For example let's assume in a future version the ClassifiedAdCreated Event should be changed to also include a Category to place ads in specific categories. So we would create an Events.V2.ClassifiedAdCreated Class which contains the additional information. The Mapping in EventMappings.cs would probably be updated to V2.ClassifiedAddCreated. But now when we load "old" events from the store, those would be mapped to the new class in our system, since they share the same EventType in the store. So we probably need to implement some upcasting/backwards compatibility in the new event class.

Do you have any ideas on how to do this? Especially when the number of version grows larger (of course this should not happen, when doing DDD and ES by the book, it should be a new event with a new name. But reality doesn't care :D). Like there may be a version 7 of the Event and we still have to support version 1 Events from the event store.

(I know, my whole example could be circumvented by creating a ClassifiedAdCategorized-Event. :) )

How to work with sub-entities following the functional approach

I finished the book and I am trying to accomplish the functional approach from the project Marketplace.PaidServices.Domain with separating aggregate state and its actions. How would you do this for ClassifiedAd in the project Marketplace.Ads.Domain? Because there are events that are passed to the child entity Picture when it's Added or Resized:

// picture
case V1.PictureAddedToAClassifiedAd e:
    picture = new Picture(Apply);
    ApplyToEntity(picture, e);
    _pictures.Add(picture);
    break;

case V1.ClassifiedAdPictureResized e:
    picture = FindPicture(new PictureId(e.PictureId));
    ApplyToEntity(picture, @event);
    break;

The examples OrderState and ClassifiedAdState don't have any entities and I can't figure out how to solve the problem with picture = new Picture(Apply). The reason is because previously the child entity recieved the Apply method from its AggregateRoot and with the functionnal approach, I can't manage to get it working.

Any idea how this approach can be done?

Separating the Domain Models from Data Models

Is it okay to separate the domain models and data models and instead use translators/mapper to convert one to another?
Although when we create the domain models we use the methods of the domain models e.g SetTitle so we ensure that the domain model is in good shape. but what happens when EF retrieves the data from db and through reflection sets the property values while someone made a mistake and changed the data directly on the DB? That bad data for instance in a finance application can cause lots of miscalculations till someone realizes it.

The sample ResizePicture event is processed twice.

It can be reproduced (but not clearly tested) with following test (put a break point in the when method of the picture class).
You will notice that the following code is executed twice:

case Events.ClassifiedAdPictureResized e:
                    Size = new PictureSize{Height = e.Height, Width = e.Width};
                    break;

Since the handling is an idempotent operation, there is no harm (that's why the test is not failing), but in case of non-idempotency it would give nasty results.

The test:

 [Fact]
        public void ShowMeTheProblem()
        {
            _classifiedAd.SetTitle(ClassifiedAdTitle.FromString("Test ad"));
            _classifiedAd.UpdateText(ClassifiedAdText.FromString("Please buy my stuff"));
            _classifiedAd.UpdatePrice(
                Price.FromDecimal(100.10m, "EUR", new FakeCurrencyLookup()));
            _classifiedAd.AddPicture(new Uri("http://localhost/storage/123.jpg"), new PictureSize(1200, 620));
            _classifiedAd.ResizePicture(_classifiedAd.Pictures.First().Id, new PictureSize(1209, 629));
            _classifiedAd.RequestToPublish();

            Assert.Equal(ClassifiedAd.ClassifiedAdState.PendingReview,
                _classifiedAd.State);
        }

Chapter 5 Unit Tests dont run

Hi,
The unit tests cannot run in chapter 5. I have even resorted to copying and pasting from here but they fail. The reason is each Event Applied raises the EnsureValidState method and the state is not valid from the very first call.

For example
public void Cannot_publish_without_price() { _classifiedAd.SetTitle(ClassifiedAdTitle.FromString("Test ad")); _classifiedAd.UpdateText(ClassifiedAdText.FromString("Please buy my stuff")); Assert.Throws<InvalidEntityStateException>(() => _classifiedAd.RequestToPublish()); }

when that test is run it fails on the first line due to

protected void Apply(object @event)
        {
            When(@event);
            **EnsureValidState();**
            _events.Add(@event);
        }

the state of the Ad is not yet valid so the exception is thrown before it gets to the assert.

What do you recommend?

Upgrade .NET Core

The projects in the repository are all set to run on .NET core 2.2 which is out of support and Microsoft discourages the installation.

Code for Chapter 13 is missing the Marketplace.Ads.Tests project

The Marketplace.sln file for Chapter 13's code references a project called Marketplace.Ads.Tests which it expects to find in a subfolder of the Chapter13 folder called "tests".

Unfortunately, the Chapter13 folder does not contain a "tests" folder, so loading the Marketplace.sln solution results in errors stating that the Marketplace.Ads.Tests project can't be found.

How about integration events ?

Hi @alexeyzimarev ,

first let met say that, it's the first time a buy a dev book and I'm not disappointed about it.
I did learn so much with your approach, it's clear, well explained, the examples are great and the code is not overkilling me.

I have a point :
I need to exchange some event (integration event if I'm right) between bounded contexts, and thus between Microservices, using a message broker.

  1. But where the publish of this event is supposed to be played ? If we take the ClassifiedAds aggregate as example, where the publish of the event is supposed to be placed in your point of view ? At the end of the Apply method of aggregate roots ? (you briefly talk about it in Chapter 5 p141 but it was before you build your entire class logic)

  2. When we construct back our aggregate from the event store (in case of event sourcing), we replay all the events, but how avoiding sending some integration event that may lead to confusion : example an event that trigger an email sending to a customer on an order shipped, we don't want to send an email each time we construct our aggregate back from scratch.
    What are the best practices ?

Many thanks

Book and code file differences

I'm currently on chapter 7 of the book and so far the code files don't always match the content in the book. As a result I'm struggling to add the code myself whilst working through the chapters as it is either already there in the previous chapters code file, or it has been implemented in a way that doesn't match the book.

For example, chapter 6, page 150 introduces us to the api section....

image

but this section has already been implemented in the chapter 5 code file here

Another example is in chapter 8, page 219 which mentions the IClassifiedAdRepository repository for the first time.....

image

Yet this already has an implementation in the chapter 5 code file here

Another example is the RetryingCommandHandler<T> described in chapter 6. This is nowhere in the chapter 6 folder.

And so on....

As someone completely new to DDD who hasn't built much software before, I had hoped I could use the code files as a starting point for each chapter and add the code from the book. After finishing the chapter the solution would then be identical to that chapters code file. Unfortunately this doesn't appear to be the case.

Chapter 8: Loading Aggregate from DB causes missing _applier in Entities

Hey, I think there is a problem with Entities when reloading Aggregates from DB. When Pictures have been added to a ClassifiedAd and we retrieve back the aggregate from DB, the _applier is missing as the objects are constructed by RavenDB. The problem is that the Apply-Method is only added in the When-Method:

                // picture
                case Events.PictureAddedToAClassifiedAd e:
                    picture = new Picture(Apply); // Apply added
                    ApplyToEntity(picture, e);
                    Pictures.Add(picture);
                    break;

When ClassifiedAd is recreated from DB, Pictures have no Apply-Method given from parent ClassifiedAd. This leeds to the error Object reference not set to an instance of an object. when I try to resize a picture. The error occured in Entity.cs:
--> When(@event) commented out because of The sample ResizePicture event is processed twice. #2

    protected void Apply(object @event)
    {
        // When(@event);  -> Prevent double processing
        _applier(@event); // Error occures here
    }

I created a workaround by extending the classes AggregateRoot, ClassifiedAd, Entity and ClassifiedAdRepository.

In AggregateRoot.cs, we force to implement a method to execute when an ClassifiedAd has been loaded from DB:

        public abstract void Initialize();

So in ClassifiedAd.cs, we need to implement this method. We go through all pictures and gives them the needed Apply method:

        // Method to handle the persistence (loading)
        public override void Initialize()
        {
            if (Pictures != null && Pictures.Any())
                Pictures.ForEach(x => x.Initialize(Apply));
        }

Therefore, we need following changes in Entity.cs:

        // BEFORE: private readonly Action<object> _applier;
        private Action<object> _applier;
        ...
        // BEFORE: protected Entity(Action<object> applier) => _applier = applier;
        protected Entity(Action<object> applier) => Initialize(applier);

        // Method to handle the persistence (loading)
        public void Initialize(Action<object> applier) => _applier = applier;

Finally, in ClassifiedAdRepository.cs, we need to execute the Initialize method when a ClassifiedAd has been loaded:

        public async Task<ClassifiedAd> Load(ClassifiedAdId id)
        {
            var ad = await _session.LoadAsync<ClassifiedAd>(EntityId(id));
            ad.Initialize();
            return ad;
        }

Please let me knwo what you think about it. Maybe there is a better solution? (apart from going with event sourcing where all events in the When method get applied).

Chapter 12 referring to next chapter which isn't there

In several places in Chapter 12 it is mentioned that some topics will be handled in a next chapter:

Bringing sanity to domain models is the most important topic and we will touch upon the implementation details in the next chapter.

The topic of cross-context communication will be briefly touched upon in the next chapter, but even now I can tell you that it happens by the same Tell, Don't Ask principle.

But we definitely must ensure that keeping the information in sync is reliable, which is something we will be looking in the next chapter.

But Chapter 13 doesn't cover these items. Trying to apply DDD and the bounded context principle already quiet some time now, it would be interesting to know your insides on how implementing the above topics in practice.

How to validate/prevent invalid state transitions in ClassifiedAd?

Hi!
I really enjoyed the book so far. I just started to play around with what you teach and how to use the whole DDD-Framework-Classes to fiddle around with my own business case.

And now i stumbled upon the problem, that i have no idea on how to prevent an invalid state transition inside my aggregate.

Let's imagine my boss decides, that a ClassifiedAd once published shall not be changed. Meaning setting the title and text should not be possible anymore. I currently don't see how this use case could be solved with the current foundation based on the AggregateRoot.Apply() method, since it would just update the text via the When() method. Afterwards it would call the EnsureValidState() method which would be totally fine. Additionally EnsureValidState() is unable to detect this change at all. So we push the new Event into our local changes and everything would look fine. Beside the fact that we changed the title of an already published ad which we don't want to allow.

So the only two possible options to solve this i see are:

  1. Validate the state transition inside of the setter. So calling SetTitle when in the Published-State would not emit a new event. Prevent the update. But this feels wrong, since we tried to centralize the whole validation with the EnsureValidState method.
  2. Check if it's valid to change the title inside the When() method when processing a TitleChangedEvent. This would work, as long as we don't try to replay old Event-Streams which were created before we chnged the rules. So we generally don't want to validate inside of When().

Could you please share some advice on how to do this? Or is this even something that should not be placed inside the Aggregate but more like the surrounding Manager?

Error trying to create a new user

I really enjoy the book and the examples but I am having an issue with the final project (Chapter13). I executed the code using the Visual Studio and I am having an error when I try to create a new user using the register form. Once I enter the user information and click "SIGNUP", the server returns the follwing error:
""
[10:48:01.988 DBG] () Marketplace.Users.UserProfiles.UserProfileCommandsApi Handling HTTP request of type "UserProfile"
[10:48:02.494 ERR] () Marketplace.Users.UserProfiles.UserProfileCommandsApi Error handling the command
System.NullReferenceException: Object reference not set to an instance of an object.
at Marketplace.EventSourcing.ApplicationService1.Handle[TCommand](TCommand command) in C:\work\T4ISB\.Net Core\DDD\Hands-On-Domain-Driven-Design-with-.NET-Core-master\Chapter13\src\Marketplace.EventSourcing\ApplicationService.cs:line 26 at Marketplace.WebApi.CommandApi1.HandleCommand[TCommand](TCommand command, Action`1 commandModifier) in C:\work\T4ISB.Net Core\DDD\Hands-On-Domain-Driven-Design-with-.NET-Core-master\Chapter13\src\Marketplace.WebApi\CommandApi.cs:line 35
""

Thank you

Still receiving "The entity of type 'ClassifiedAdTitle' is sharing the table 'ClassifiedAds'"

Nearing completion of Chapter 8, I received the error as advised in the book when attempting to set an ad's title or text:

{
  "error": "The entity of type 'ClassifiedAdTitle' is sharing the table 'ClassifiedAds' with entities of type 'ClassifiedAd', but there is no entity of this type with the same key value '{ClassifiedAdId: 52b7f389-2874-45bc-a315-5552505de551}' that has been marked as 'Added'.",
  "stackTrace": " at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.Validate(Dictionary`2 sharedTablesCommandsMap)\n
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.CreateModificationCommands(IList`1 entries, IUpdateAdapter updateAdapter, Func`1 generateParameterName)\n
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommands(IList`1 entries, IUpdateAdapter updateAdapter)+MoveNext()\n
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple`2 parameters, CancellationToken cancellationToken)\n
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple`2 parameters, CancellationToken cancellationToken)\n
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)\n
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)\n
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)\n
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)\n
   at Marketplace.Api.ClassifiedAdsApplicationService.HandleUpdate(Guid classifiedAdId, Action`1 operation) in /Users/will/src/Marketplace/Marketplace/Api/ClassifiedAdsApplicationService.cs:line 74\n
   at Marketplace.Api.ClassifiedAdsCommandsApi.HandleRequest[T](T request, Func`2 handler) in /Users/will/src/Marketplace/Marketplace/Api/ClassifiedAdsCommandsApi.cs:line 46"
}

As recommended in the book, I attempted a fix by proving the Null Value constants eg:

public static ClassifiedAdTitle NoTitle = new ClassifiedAdTitle();

and used them in the event handler case Events.ClassifiedAdCreated e::

                case Events.ClassifiedAdCreated e:
                    Id = new ClassifiedAdId(e.Id);
                    OwnerId = new UserId(e.OwnerId);
                    State = ClassifiedAdState.Inactive;
                    Title = ClassifiedAdTitle.NoTitle;
                    Text = ClassifiedAdText.NoText;
                    ClassifiedAdId = e.Id;
                    break;

However, this still caused the same error.

Being new to EF, I'm struggling to diagnose the exact problem, but I did fix it by applying this hack, which is obviously far from perfect, but does remove the symptom:

public static ClassifiedAdTitle NoTitle = new ClassifiedAdTitle("a_fake_value");

The commit I expected to fix this in is at paulspencerwilliams/HandsOnDomainDrivenDesignWithDotNETCore@5539fd9

Question on user and tenant details

Hello Alexey.

Great book. I've put a great deal of time to it. Needless to say, I would recommend it without any doubt to anyone who has interest to dive deep into DDD straight away.

I have one question that is not touched in the book, and it would be great if you can share some high level guidelines on what would be your approach on it. I am talking about tenancy and entity user related information -eg who created the record, when, related tenant - Not sure where this should be. Perhaps extending the Entity and Agregatte root classes? Makes sense to me but it kind of pollutes these entity boundaries.

Thanks,
Jorge.

How to ensure UI is consistent when read models are updated asynchronously?

@alexeyzimarev Really greal book, maybe the best book about event sourcing at present!

One question: what is your preferred way to ensure UI is consistent after executing a command that triggers async update to read model?

For example, we have single page application for task management. An user opens some task. The frontend query the backend and retrieves the task attributes from the corresponding read model. The user then presses "Close" button, which executes the command to close the task. As a result of the closure, the read model is updated asynchronously (the status of the task goes to "Closed" or to some other status, depending on the business logic of closing the task, the frontend knows nothing about it). After successfully running the command, the frontend reads the model again. How can we ensure that the read model is updated by then?

In the ClassifiedAd class, the Picture collection is not instantiated when doing a re-hydrate.

The ClassifiedAdd class has:

  public List<Picture> Pictures { get; private set; }

which is initialized in the following constructor:

 public ClassifiedAd(ClassifiedAdId id, UserId ownerId)
        {
            Pictures = new List<Picture>();
            Apply(
                new Events.ClassifiedAdCreated
                {
                    Id = id,
                    OwnerId = ownerId
                }
            );
        }

That's working fine but not in the re-hydrate scenario because the aggregate root doesn't touch that constructor when the event sourcing machinery is setting up via reflection the aggregate root.
A potential fix is to initialize the collection directly as follows:

public List<Picture> Pictures { get; private set; } = new List<Picture>();

Chapter 13

Hi

i am trying to run chapter13 solution but the program blows up on this line of code.
// Everything we proxy is hardcoded to target http://localhost because:
// - the requests are always from the local machine (we're not accepting remote
// requests that go directly to the create-react-app server)
// - given that, there's no reason to use https, and we couldn't even if we
// wanted to, because in general the create-react-app server has no certificate
var targetUriTask = portTask.ContinueWith(
task => new UriBuilder("http", "localhost", task.Result).Uri
);

Below is the error
System.AggregateException: 'One or more errors occurred. (The NPM script 'serve:bs' exited without indicating that the Vue development server was listening for requests.

"protected override void EnsureValidState()" in chapter 5.

a) "override" gives an error.
b) The compiler in VS 2017 gives errors regarding the content of the method.
"Operator '&&' cannot be applied to operands of type 'bool' and type'.....' ".
Also it gives errors regarding missing parenthenses and ";".

Marketplace.Domain.ClassifiedAdTitle. A class should either have a default constructor....

When testing the developed application, at the end of Chapter 6, whilst running the server in between API posts, all seems to work fine, most likely due to Raven's document cache. However, if I restart the app in between API posts, I'm presuming the lack of Raven client cache means it's client has to pull documents from the database, and deserialisation fails with:

      Connection id "0HLQQ0FOTFTT7", Request id "0HLQQ0FOTFTT7:00000001": An unhandled exception was thrown by the application.
System.InvalidOperationException: Could not convert document ClassifiedAd/a287c0ad-898f-4160-9fa1-e005c778759a to entity of type Marketplace.Domain.ClassifiedAd
 ---> Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Marketplace.Domain.ClassifiedAdTitle. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Title.Value'.

I can see that persistence is generally working however, when viewing the document store, amount 321 has been updated several times...

{
    "Id": {
        "Value": "a287c0ad-898f-4160-9fa1-e005c778759a"
    },
    "State": "PendingReview",
    "OwnerId": {
        "Value": "a287c0ad-898f-4160-9fa1-e005c778759a"
    },
    "Title": {
        "Value": "the title"
    },
    "Text": {
        "Value": "the text"
    },
    "Price": {
        "Amount": 321,
        "Currency": {
            "CurrencyCode": "EUR",
            "InUse": false,
            "DecimalPlaces": 0
        }
    },
    "ApprovedBy": null,
    "@metadata": {
        "@collection": "ClassifiedAds",
        "Raven-Clr-Type": "Marketplace.Domain.ClassifiedAd, Marketplace.Domain"
    }
}

I'd imagine this doesn't really matter based on the context of the book, but has certainly brought doubt in my mind as to my following of the code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.