 .NETConf. Do you want to introduce yourself and then take it away? Yep. Hello. Can you see my screen? Yep. We can see you perfectly. Hello. Hello. Yep. All good. Okay. Let's get started. Hello, friends. Welcome to the .NET conference 2018. My name is Ting. I'm from Vietnam. I am the maintainer of the Simulcomer. As some of you may know, Simulcomer is an open-source cross-platform modular e-commerce built on the .NET Core. Today, I will talk about modular architecture with a .NET Core. It is not my first language, so I'm sorry if I don't pronounce correctly. Yeah. Okay. Thank you. This is a slide about myself, but I think you can check out it later if you're interested. This is the agenda of my talk. First, I will briefly introduce you about modular architecture. Then I will talk about how we apply modular architecture in Simulcomer. And finally, I will show you some early work from the .NET team that can help us to apply the modular architecture easier. So, this is the picture of modular architecture. In the modular architecture, the application is divided into many modules. For example, in the case of an e-commerce application, we can have customer module, product module, order module, payment, shipping, and it's just right. Normally, one module is one project in Visual Studio that can be developed separately. Then, eventually, on the module, we will deploy it into a single web host. And normally, we usually have only one database for an entire application. It is different a bit to compare with myro-services architecture. In myro-services architecture, every service is deployed into their own host. And in myro-services, normally, there are many database. For my observation, a module can be added or removed in two ways. First, we add the development time. That means if we want to add a module to the application, we have to add reference to it, then rebuild and redeploy the application. The second approach is to be able to add the module at a runtime. That means somewhere in the application, we will have a UI for the user to find, to download, to install a module directly on the fly without rebuild or redeploy the application. Some kind like WordPress. I know many of us know WordPress. And it is very convenient for the user. But it is very hard for developers to enable this in our ABDecore application. And I will tell you why along the presentation. So, what is the benefit of being modular? There are a lot of benefits of being modular here some. First, separation of concern. Every module only cares about one particular problem in the app. For example, the product module only cares about product and the other module only cares about order. Second, it is easier to add, remove or modify a module without affecting to the rest of the application. And in some situations, the user can choose which module they want to add into the application and if they don't want to use some particular module, they can remove it. For example, in some customers, they only want to have a website to show their product but they don't sell them. In that case, they can use only the product module and they can remove the order module like order shipping payment and so on. Third, a module can be easily developed in parallel. This is extremely important for the BIT project that is developed by different teams. And finally, well modular architecture can help our code easier to read and easier to maintain. Although there are many benefits of being modular, however, there are also some challenges. The biggest challenge I think is they know support, they know native support. I could not find any document or guide live from Microsoft about how to apply modular architecture for the ABnet Core application. And I had to do a lot of work around to be able to apply this architecture and sometimes it is hard to separate modules properly. You know, sometimes we don't know where, sometimes we don't know which module to put the code into. Things are not black and white, things are not all white, black and white. And to be able to separate modules properly, we had to understand deeply about the domain knowledge. And finally, when we have a lot of modules, it is hard to manage the dependency. There are two kinds of dependencies. The first is dependency between the modules. For example, a module order must depend on the module product. We cannot order without a product price. But this is only the one-way dependency. The order depends on the product, but the product cannot depend on the order. And the second type of dependency is the dependency of the library because a module can be developed by a different team. And maybe there are some cases, a multiple version of one library is used. For example, the order, the product module is used to map version 7. And the shipping module is used to map version 6, for example. Okay, now let's talk a bit about Simulcomic. I'm going to open our repository in the GitHub. Simulcomic is a cross-platform modular e-commerce system built on the .NET Core. I have started to build this project in January 2016. That means more than two years from now. At the beginning, it's just like a sample project for me to practice the .NET Core. But after receiving a very good reaction from the community, you see we have a lot of stuff. And then I got motivated. Then after a lot of sleepless nights and a lot of weekend, now Simulcomic is a big project that has a lot of modules. Currently we have around 30 modules for entire the app. We have order, we have inventory, we have shipping, we have payment and many more. This is the home page of the project. Simulcomic can run on any platform. It can run on Docker, on Windows, in Linux, or Mac. And we have tested it on SQL Server, port 3, MySQL, or SQLite. And it's free, it's free and open source. Here we can take a look up online demo of the application. This is a new team I had just built some weeks ago. For example, we can go to the product detail. We can support the product can have many variations like the color and the size. And we had writing and review also. Okay, now let's go through the code. I will show you how we apply modular architecture in Simulcomic. Now here I have Visual Studio open. And this is the Simulcomic solution. There are 34, there are 42 projects. And I will do the infrastructure. The infrastructure here is like some utility or helper. And this download logic is like this. And this is the network host. The host is on the IBM network to our application. It is applied by a shell to lot and time. In every module, every module will contain all the material for the module to be able to run. It has like the model, the domain model. This domain model will be mapped to the database. And it has controller. It has view component. And in Simulcomic, we use like generate database. But sometimes we need some methods beyond the generate repository. We can implement the custom repository here. And we can have the services to do some business logic and also the view. All the started content like CLS and generate also put into a module also. The other module similar. And now we have a lot of modules. How the MVC know and lost our module in the application. So let's take a look up there. Oh, I'm sorry. I have missed one important thing. In the module, they want file called module.json. And this is the file we can put the metadata for our module. For example, the name of the module, the version of the module. And they want interesting property. We call a bundle with the host. Each value can be two or four. If the value is set to two, that means this module is bundled with the host. That means we cannot lie and turn them. This feature is added recently to enable the faster start-up and the smaller deployment footprint. The concept is some kind of similar to AB.net to the AB.net meta packet like Microsoft, ABnet.app or Microsoft.abnetcore.on. And if we set this property to two, we had to add referendum in the web host. If we set the value is four, and then we don't need to referendum in the web host. Okay. Then actually on the module, we will copy into the web host. In the web host, there's also a folder called module. And we have many on the module also can be found here. But it is the reliable version of the module. It contains no C-sharp code. It just contains maybe some binary or the view. And yeah, and maybe all the stuff for the application to run. And the static content is copied into the WWW route of the host. For example, you can see that we had a CMS module. We had a WWW route. And on the content of the WWW route, here we will copy to the WWW route of the host module and CMS. Here. The copying of the project is done by using a custom MS build task. Here, as you can see, we do some custom events after the target build. That means after the build event of the web host, we call a group command to copy and tie the module to the web host. Let's take a look at the web host. Sorry, let's take a look at the group file. Here, the group file is quite simple. Here, we can define some variable. And then we will load and tie the module. Here, we will look for the module.json. And then the copy module. The copy module will call the copy static. In the copy static, we will copy on the view the module.json. And maybe some other stuff. Here, you can see that if the module is not bundled with the host, we need to copy the build output of that module. So, later on, if we want to remove a module, we can only delete the folder of the module. Now, all the content on the module are copied to the web host. And now, when the applications start up, how the admin call loads our module. So, let's take a look at the startup.cs. Here, in the configure service, we can load in knowledge module. Let's go down to the implementation of that method. In that method, we will first look for the module folder in the web host. Then we will look through and tie the module in that folder. If the build folder exists, that means the module is not bundled with the host. We have to load them manually. So, let's go down to the load module method. Here, we will look through on the assembly of that module and view assembly load content to load them. Sometime, an assembly might be loaded in the previous module. In that case, an exception will be through. And we cast the exception and we get the loaded assembly. And here, we also compare the version. For example, if the AutoMap version A has been loaded, now we want to like to load another version of AutoMap, it will rule an exception. Then, we will look for the main assembly of the module. In the module, it might be in the directory of the module. It might be the main assembly. So, we can take a look at here in the bin. And here, this is on the assembly in the cmd module. We can see there are many assembly. Then, we have to look for the main assembly of the module. That means symbol, comma, dot, module, dot, cmd, the main assembly. After that, we can have on the assembly of the module loaded. But MVC doesn't know about them. So, we had to re-register our assembly with the application path. This is one of the cool features of the AFB.NET Core to support the like this kind of application. Here, we will look through the main assembly, up on the module and re-register them with the application path. Okay. Next, how the MVC can find our view. Because our view is not in the view folder. As you can see, our module is sitting here, not in the view as normally. So, to let the MVC know how to find the view, we had to implement a custom view expander location. So, I can show you the course here. We can module view location expander. That's in Laman and the interface of view location expander. And in this method, we will look for the controller that is serving the request. Then, we will look for the module.content.controller. Then here, we will write the view engine to find the view for that module. Here are some other logic to enable the live dynamic team. Then, how about the dependency injection? In the simple command, we use autofact to re-register on the assembly of the module. Let's see the code here. After we had on the main assembly up on entire module, we will look through those assembly and we will re-register on the tie. Again, sorry, on the tie and with reverse story service provider and handler. But in many cases, our module needs to re-register dependency by itself. And here, we also support that scenario. So, let's take a look at the module. In our module, we can create a class that implement the interface called iModuleInitializer. There are two methods in that interface, configure and configure service. Those two methods are very like the configure and the configure service in the app. We can start up and let's take a look at the here. In the configure service in the startup file of the host, we will find out on the implementation of the interface iModuleInitializer and we call configure service to re-register the dependency of a module. And similarly in the configure service, we also call the configure methods for module. Okay, then how about the database? How about in simple command, we use entity framework core and how we cut my, let's say, what we did to enable entity framework core to support the modular architecture. So, per my observation, there are two approaches to enable the, to make it happen in the modular architecture like this. The first is one TV contact for module. Every module will maintain their own TV contact. This approach is like, actually this approach is slightly very complicated because when the application has many TV contact and it's hard to manage them. The second approach is one TV contact for entire application. And in simple command, we would like to keep things as simple as possible. So we have chosen the one TV contact for entire application. So let's take a look at the TV contact here. The simple TV contact. And on the module, let's take a look at on module reactant methods. Here we will get on the type of every module and we add to a list called type to register. And after that, we call the register entity where we will find on the class that inherits from the entity page and we register them with the simple TV contact. And after that, we also make some customization on the convention. To match our database look modular, we have an element convention for the table name. So let's take a look at the database. So it is the database of simple command. So as you can see here, the table name will have the refresh. It's the module name. For example, the menu table of the module name will have CMS underscore menu. We have catalog, we have CMS, we have call, we have order, and so on. There are around 80 tables in simple command. But sometimes convention is not enough. And in many scenarios, we would like to do some custom mapping for our entity. In that case, we can create a class in the interface and say I custom motor by the and in the build method, we can map, we can write our custom mapping here. For example here, I want to map the name of the ASB.NET entity table. So we had a call run. And here we can do some relationship. And the cheat data also be implemented here. Here we cheat the data for our application. Okay, this is almost on the thing on how we apply modular architecture in simple command. Let's get back to the slide. We have done the demo. And I see there are some limitations of the modular architecture in simple command currently. The first limitation is adding or removing module will require the website to be restarted. Currently, it is also the limitation of .NET Core. In .NET Core, there is no way to unlock an assembly. And the second limitation I can see is currently we have one support side by side dependency. For example, one module you have to map version 7 and the other module you have to map version 6. When both two modules are bund together, they will prove an exception. But I see the problem maybe we can resolve it in the future. Observation, I see a very good prototype from Nightmatch Master. So we can see his blood pod here. In this blood pod, he has made some prototype and it plans how we launch the blood in. And here we utilize many assembly logic contacts In simple command, we use only one default assembly logic contacts for all modules. But in Night's approach, he uses each assembly logic contacts for modules. That means he has many assembly logic contacts in the application. And with this approach, he can support side by side dependency. And the other good news is that recently there is a point where that enables unlocking an open assembly contact not being much to the .NET Core CR repo. And so maybe we can unlock the assembly in the future soon. So this point we will be in March 22 days ago. Okay, there are some little time I would like to show you about the team in Chimokomak. For example, this is one team. And here we have, we can, oh, sorry. There are some problems with the certificate. I don't know why. This is the application where we can manage our Chimokomak website. Here in the team, we can utilize another team. Here we can, like, each team is currently used. And we can change to another team. And maybe we can also download the team. So I want to apply this. And if we want to go to the home page. So yeah, you can see the team is changed. And we don't need to rebuild or to redeploy the application. It just happened on the fly. It's very easy to build a new team for Chimokomak. To build a new team for Chimokomak, all we need is to create a founder in the team, founder of the host. For example, in this solution, we have two teams. And in this founder, we have the team.json where we put on the metadata for our team. And then we normally, we will override the layout for our team. We can use each team their own layout. In this layout, we can reference to the different sets of the JavaScript or different CSS, different stylesheet. And if you want to, sometimes we also would like to modify the structure of the HTML. In that case, we can override the view. So we can create a view. And the location of the view has to be the same as the location of the original view. Normally, we will buy on the structure of the view here and we will create another view in that location. And if the view.ng file, the custom view here, it will automatically override the original view. And here, in the developer route, there also contains a founder called team. And then we have the team name and we can put the static content for our team here. And that's it. That's all we need to do the custom team for Schimelkermack. And this also on the content I would like to share with you today. And now I'm happy to answer the question that you may have. Thank you. Do we have any questions? Monsayn is doing a great job. So for the platform, how long ago did you start working on it? I have been working on it for more than two years. One or two years? What made you start with it? Yeah. Sorry. What made you start the platform, the project? Actually, two years ago, when I want to study about the net core, and I want to practice my skill, and then I create this project for practicing. But after that, I got a very good reaction from the community. And then I got motivated. And then I developed it until now. That's great. Hey, I was going to say that I have a question in here from Ancient Coder. He's asking, that platform looks amazing. Is it open source? Yes. It's completely open source and free on-show. So show me how would I go about getting it? In case Ancient Coder missed it but other people are joining the channel. Okay. You can look at the repository in the GitHub. Yeah. You can find github.com. Slash symbol.com. And this is the AbbotG license. That means completely open source and free on-show on the course and on the implementation on the working doing here. Well, that's amazing. So what kind of help do you need for this? Because obviously I know you probably have a job. You're busy. You probably have family. So what kind of stuff would you like people to help you with in this open source project? Which by the looks of it, everybody's saying, oh, wow, this is hard. Ancient Coder said, wow, that's great. Thanks so much for sharing your hard work with the community. So how can people help you? Yeah, it's very easy. You can like, you can take a look at this project and you can suggest the feature. You can help to find out the bug. You can help by fixing the bug or implementing the feature. Yeah, we have a lot of work needs to be done here. And you can pick one of them to do and then submit the pull request. So everybody out there on the Twitter channel, hey, if you guys have any spare time, help Thien out with simple commerce from your looks, from base of the comments, everybody's loving it. It's a great platform. Thien, thank you so much for contributing your time and your efforts to the community. It is projects like these that make the Dynan community to be an awesome place to be and work with. All right, I don't think we have any more questions. Okay, thank you. I will talk to you later. Okay, thank you. Thank you so much. Thank you, everyone.