public async Task <IActionResult> Create([Bind("EntryId,TopicId")] EntryToTopic entryToTopic)
        {
            if (ModelState.IsValid)
            {
                _context.Add(new EntryToTopic()
                {
                    EntryId   = entryToTopic.EntryId,
                    TopicId   = entryToTopic.TopicId,
                    IsPrimary = false
                });

                await _context.SaveChangesAsync();

                return(RedirectToAction(nameof(Index)));
            }
            ViewData["EntryId"] = new SelectList(_context.Set <Entry>(), "Id", "Discriminator", entryToTopic.EntryId);
            ViewData["TopicId"] = new SelectList(_context.Topics, "Id", "Id", entryToTopic.TopicId);
            return(View(entryToTopic));
        }
        public async Task <IActionResult> Edit(int id, [Bind("EntryId,TopicId,IsPrimary")] EntryToTopic entryToTopic)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(entryToTopic);
                    await _context.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                }
                return(RedirectToAction(nameof(Index)));
            }
            ViewData["EntryId"] = new SelectList(_context.Set <Entry>(), "Id", "Discriminator", entryToTopic.EntryId);
            ViewData["TopicId"] = new SelectList(_context.Topics, "Id", "Id", entryToTopic.TopicId);

            return(View(entryToTopic));
        }
        public async Task <string> UpdateEntryAsync(EditArticle form)
        {
            var article = await _entryRepository
                          .FindBy(e => e.Id == form.Id)
                          .Include(e => e.EntryToTopics)
                          .FirstOrDefaultAsync();

            var tracker = new EditTracker <Entry>();

            if (article == default)
            {
                throw new AppException(ExceptionType.ARTICLE_NOT_FOUND);
            }

            try
            {
                article.LastModified = DateTime.Now;
                tracker.Track(e => e.LastModified);

                if (article.HeadLine != form.HeadLine)
                {
                    article.HeadLine = form.HeadLine;
                    article.Slug     = GenerateSlug(form.HeadLine);
                    tracker.Track(e => e.HeadLine);
                    tracker.Track(e => e.Slug);
                }

                if (article.Paragraph != form.Paragraph)
                {
                    article.Paragraph = form.Paragraph;
                    tracker.Track(e => e.Paragraph);
                }

                if (article.Url != form.Url)
                {
                    article.Url = form.Url;
                    tracker.Track(e => e.Url);
                }

                if (article.Body != form.Body)
                {
                    article.Body = form.Body;
                    tracker.Track(e => e.Body);
                }

                if (form.Img != null)
                {
                    article.Img = _imageProcessingService.ProcessFormImage(form.Img);
                    tracker.Track(e => e.Img);
                }

                if (form.Caption != null)
                {
                    article.Caption = form.Caption;
                    tracker.Track(e => e.Caption);
                }

                _entryRepository.Update(article, tracker);
                await _unitOfWork.Commit();
            }
            catch (Exception ex)
            {
                throw new AppException(ExceptionType.ARTICLE_UPDATE_FAILED, ex);
            }

            var topicId = article.EntryToTopics.FirstOrDefault(et => et.IsPrimary)?.TopicId;

            if (topicId == default)
            {
                var existing = await _entryToTopicRepository
                               .FindByKey(article.Id, form.PrimaryTopic.Value);

                if (existing != null)
                {
                    existing.IsPrimary = true;
                    _entryToTopicRepository.Update(existing, e => e.IsPrimary);
                }
                else
                {
                    // what happens if article doesn't have a primary topic
                    // get the form primary topic and set it
                    var primaryTopic = new EntryToTopic()
                    {
                        EntryId   = article.Id,
                        TopicId   = form.PrimaryTopic.Value,
                        IsPrimary = true
                    };

                    await _entryToTopicRepository.Create(primaryTopic);
                }

                await _unitOfWork.Commit();
            }
            else if (topicId.Value != form.PrimaryTopic.Value)
            {
                using (IDbContextTransaction transaction = await _unitOfWork.BeginTransaction())
                {
                    try
                    {
                        // set new topic as primary
                        var primaryTopic = await _entryToTopicRepository
                                           .FindBy(et => et.EntryId == article.Id && et.TopicId == topicId)
                                           .FirstOrDefaultAsync();

                        primaryTopic.IsPrimary = false;

                        _entryToTopicRepository.Update(primaryTopic, e => e.IsPrimary);

                        // does this article already have this topic ?
                        var newPrimaryTopic = await _entryToTopicRepository
                                              .FindByKey(article.Id, form.PrimaryTopic.Value);

                        if (newPrimaryTopic == default)
                        {
                            await _entryToTopicRepository.Create(new EntryToTopic()
                            {
                                EntryId   = article.Id,
                                TopicId   = form.PrimaryTopic.Value,
                                IsPrimary = true
                            });
                        }
                        else
                        {
                            newPrimaryTopic.IsPrimary = true;
                            _entryToTopicRepository.Update(newPrimaryTopic, e => e.IsPrimary);
                        }

                        await _unitOfWork.Commit();

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                    }
                }
            }

            return(article.Slug);
        }