public async Task <IHttpActionResult> PostValidate([FromBody] JObject value)
        {
            var url      = (string)value["url"];
            var resource = await LibraryUtils.TryValidateResource(url);

            return(Ok(resource));
        }
        public async Task <IHttpActionResult> PostResource([FromBody] JObject value)
        {
            var start      = (int?)value["start"];
            var finish     = (int?)value["finish"];
            var hasSegment = start.HasValue && finish.HasValue;

            if (hasSegment && ((start.Value < 0) || (finish.Value < 0) || (start >= finish)))
            {
                return(BadRequest("Segment time is wrong."));
            }

            var url      = (string)value["url"];
            var resource = await LibraryUtils.TryValidateResource(url);

            // If validation is unsuccessfull, TryValidateResource returns null
            if ((resource == null) || (resource.Format != LibraryUtils.Formats.Youtube))
            {
                return(BadRequest("Resource not found."));
            }

            // Idempotent. The stored procedure returns the processed resource back.
            resource = (await DapperHelper.QueryResilientlyAsync <ResourceDto>("dbo.libCreatePersonalResource",
                                                                               new
            {
                UserId = this.GetUserId(),
                Format = resource.Format,
                NaturalKey = resource.NaturalKey,
                Segment = hasSegment ? Resource.BuildSegment(start.Value, finish.Value) : null,
                Title = resource.Title,
                CategoryIds = LibraryUtils.KnownCategories.GameCopycat,
                Tags = LibraryUtils.KnownTags.GameCopycat,
                HasVideo = resource.HasVideo,
                IsForCopycat = true,
            },
                                                                               CommandType.StoredProcedure))
                       .Single();

            var transcript = (string)value["transcript"];

            if (!String.IsNullOrEmpty(transcript))
            {
                await InternalSaveTranscript(resource.Id, transcript);
            }

            return(Ok(resource));
        }
        public async Task <IHttpActionResult> PostResource(ResourceDto resource)
        {
            ResourceDto result;

            // In the case of a new resource Id is not passed. In the case of a common resource Id has a value.
            if (resource.Id == 0)
            {
                var newResource = await LibraryUtils.TryValidateResource(resource.Url);

                // If validation is unsuccessfull, TryValidateResource returns null
                if (newResource != null)
                {
                    resource.Format     = newResource.Format;
                    resource.NaturalKey = newResource.NaturalKey;
                    resource.Title      = newResource.Title ?? resource.Title;
                    resource.HasVideo   = newResource.HasVideo || resource.HasVideo;
                }
                else
                {
                    resource.NaturalKey = null;
                }
            }

            if (resource.NaturalKey != null)
            {
                var userId = this.GetUserId();
                // Idempotent
                result = (await DapperHelper.QueryResilientlyAsync <ResourceDto>("dbo.libCreatePersonalResource",
                                                                                 new
                {
                    UserId = userId,
                    Id = resource.Id,
                    Format = resource.Format,
                    NaturalKey = resource.NaturalKey,
                    Segment = resource.Segment,
                    Title = resource.Title,
                    CategoryIds = GeneralUtils.SanitizeSpaceSeparatedWords(resource.CategoryIds),
                    Tags = GeneralUtils.SanitizeSpaceSeparatedWords((resource.Tags ?? "").Replace("-", String.Empty).ToLower()),
                    SourceId = resource.SourceId,
                    HasExplanation = resource.HasExplanation,
                    HasExample = resource.HasExample,
                    HasExercise = resource.HasExercise,
                    HasText = resource.HasText,
                    HasPicture = resource.HasPicture,
                    HasAudio = resource.HasAudio,
                    HasVideo = resource.HasVideo,
                    Comment = resource.Comment,
                },
                                                                                 CommandType.StoredProcedure))
                         .SingleOrDefault();

                // Update the search index.
                var indexHelper = new PersonalIndexHelper(DapperHelper.GetConnectionString());
                if (resource.Id == 0)
                {
                    // A new resource is added on the Personal tab. It is waiting to update the category list. Update the index ASAP.
                    await indexHelper.IndexUserResource(CancellationToken.None, userId, result.Id, true);
                }
                else
                {
                    // If a common resource is added to the personal collection, update the search index in background. Return response early.
                    //// If this task fails, the WebJob will process everything.
                    //var queueTask = AzureStorageUtils.QueueMessage(
                    //    AzureStorageUtils.WebJobsConnectionStringName,
                    //    AzureStorageUtils.QueueNames.IndexPersonal,
                    //    userId.ToString() + " " + resourceId.ToString()
                    //    );
                    //await Task.WhenAll(dbTask, queueTask);
                    HostingEnvironment.QueueBackgroundWorkItem(ct => indexHelper.IndexUserResource(ct, userId, result.Id, true));
                }
            }
            else
            {
                throw new ArgumentException("Wrong web address.");
            }

            return(Ok(result));
        }