Пример #1
0
 public static BookReview ToModel(this IBookReview review, bool details = false)
 {
     if(review == null)
     return null;
       var m = new BookReview() {
     Id = review.Id, CreatedOn = review.CreatedOn, BookId = review.Book.Id, UserName = review.User.DisplayName,
     Rating = review.Rating, Caption = review.Caption
       };
       if(details)
     m.Review = review.Review;
       return m;
 }
Пример #2
0
        public static BookReview ToModel(this IBookReview review, bool details = false)
        {
            if (review == null)
            {
                return(null);
            }
            var m = new BookReview()
            {
                Id     = review.Id, CreatedOn = review.CreatedOn, BookId = review.Book.Id, UserName = review.User.DisplayName,
                Rating = review.Rating, Caption = review.Caption
            };

            if (details)
            {
                m.Review = review.Review;
            }
            return(m);
        }
Пример #3
0
        private BookReview CreateUpdateReview(BookReview review, bool create)
        {
            Context.ThrowIfNull(review, ClientFaultCodes.ContentMissing, "Review", "Review object in message body is missing.");
            //find book
            var session = OpenSession();
            var bk      = session.GetEntity <IBook>(review.BookId);

            //Validate using ValidationExtensions methods
            //will throw and return BadRequest if book Id is invalid
            Context.ThrowIfNull(bk, ClientFaultCodes.ObjectNotFound, "BookId", "Book not found. ID={0}", review.BookId);
            //Validate input fields
            Context.ValidateNotEmpty(review.Caption, "Caption", "Caption may not be empty.");
            Context.ValidateNotEmpty(review.Review, "Review", "Review text may not be empty.");
            Context.ValidateMaxLength(review.Caption, 100, "Caption", "Caption text is too long.");
            // Review text is unlimited in database, but let's still limit it to 1000 chars
            Context.ValidateMaxLength(review.Review, 1000, "Review", "Review text is too long, must be under 1000 chars");
            Context.ValidateRange(review.Rating, 1, 5, "Rating", "Rating must be between 1 and 5");
            Context.ThrowValidation(); //will throw if any faults had been detected; will return BadRequest with list of faults in the body
            // get user;
            var user = session.GetEntity <IUser>(Context.User.UserId);

            // with AuthenticatedOnly attribute, we should always have user; still check just in case
            Context.ThrowIfNull(user, ClientFaultCodes.ObjectNotFound, "User", "Current user not identified.");

            //Create/update review entity
            IBookReview entReview;

            if (create)
            {
                entReview = session.NewReview(user, bk, review.Rating, review.Caption, review.Review);
            }
            else
            {
                entReview = session.GetEntity <IBookReview>(review.Id);
                Context.ThrowIfNull(entReview, ClientFaultCodes.ObjectNotFound, "Review", "Review object not found, ID={0}.", review.Id);
                entReview.Caption = review.Caption;
                entReview.Rating  = review.Rating;
                entReview.Review  = review.Review;
            }
            session.SaveChanges();
            return(entReview.ToModel(details: true));
        }
Пример #4
0
 public BookReview UpdateReview(BookReview review)
 {
     return(CreateUpdateReview(review, create: false));
 }
Пример #5
0
 public BookReview AddReview(BookReview review)
 {
     return(CreateUpdateReview(review, create: true));
 }
Пример #6
0
 public BookReview AddReview(BookReview review)
 {
     return CreateUpdateReview(review, create: true);
 }
Пример #7
0
        private BookReview CreateUpdateReview(BookReview review, bool create)
        {
            Context.ThrowIfNull(review, ClientFaultCodes.ContentMissing, "Review", "Review object in message body is missing.");
              //find book
              var session = OpenSession();
              var bk = session.GetEntity<IBook>(review.BookId);

              //Validate using ValidationExtensions methods
              //will throw and return BadRequest if book Id is invalid
              Context.ThrowIfNull(bk, ClientFaultCodes.ObjectNotFound, "BookId", "Book not found. ID={0}", review.BookId);
              //Validate input fields
              Context.ValidateNotEmpty(review.Caption, "Caption", "Caption may not be empty.");
              Context.ValidateNotEmpty(review.Review, "Review", "Review text may not be empty.");
              Context.ValidateMaxLength(review.Caption, 100, "Caption", "Caption text is too long.");
              // Review text is unlimited in database, but let's still limit it to 1000 chars
              Context.ValidateMaxLength(review.Review, 1000, "Review", "Review text is too long, must be under 1000 chars");
              Context.ValidateRange(review.Rating, 1, 5, "Rating", "Rating must be between 1 and 5");
              Context.ThrowValidation(); //will throw if any faults had been detected; will return BadRequest with list of faults in the body
              // get user;
              var user = session.GetEntity<IUser>(Context.User.UserId);
              // with AuthenticatedOnly attribute, we should always have user; still check just in case
              Context.ThrowIfNull(user, ClientFaultCodes.ObjectNotFound, "User", "Current user not identified.");

              //Create/update review entity
              IBookReview entReview;
              if(create)
            entReview = session.NewReview(user, bk, review.Rating, review.Caption, review.Review);
              else {
            entReview = session.GetEntity<IBookReview>(review.Id);
            Context.ThrowIfNull(entReview, ClientFaultCodes.ObjectNotFound, "Review", "Review object not found, ID={0}.", review.Id);
            entReview.Caption = review.Caption;
            entReview.Rating = review.Rating;
            entReview.Review = review.Review;
              }
              session.SaveChanges();
              return entReview.ToModel(details: true);
        }
Пример #8
0
 public BookReview UpdateReview(BookReview review)
 {
     return CreateUpdateReview(review, create: false);
 }
Пример #9
0
        public void TestClientFaults()
        {
            var client = SetupHelper.Client;
              Logout(); //if we're still logged in from other failed tests

              const string booksUrl = "api/books";
              const string reviewUpdateUrl = "api/user/reviews";

              //Get c# books
              var csBooks = client.ExecuteGet<SearchResults<Book>>(booksUrl + "?titlestart={0}", "c#");
              Assert.IsTrue(csBooks.Results.Count > 0, "Failed to find cs book");
              var csBk = csBooks.Results[0];

              // Test - anonymous user posts review - server returns BadRequest with AuthenticationRequired fault in the body
              var goodReview = new BookReview() { BookId = csBk.Id, Rating = 5,
            Caption = "Wow! really awesome!", Review = "Best I ever read about c#!!!" };
              var cfEx = TestUtil.ExpectClientFault(() => client.ExecutePost<BookReview, BookReview>(goodReview, reviewUpdateUrl));
              Assert.AreEqual("AuthenticationRequired", cfEx.Faults[0].Code, "Expected AuthenticationRequired fault.");

              //Login as diego, post again - now should succeed
              this.LoginAs("Diego");
              var postedReview = client.ExecutePost<BookReview, BookReview>(goodReview, reviewUpdateUrl);
              Assert.IsNotNull(postedReview, "Failed to post review");
              Assert.IsTrue(postedReview.Id != Guid.Empty, "Expected non-empty review ID.");

              // Now bad posts - review objects with invalid properties; See CatalogController.PostReview method
              // first try sending null object
              cfEx = TestUtil.ExpectClientFault(() => client.ExecutePost<BookReview, BookReview>(null, reviewUpdateUrl));
              Assert.AreEqual("ContentMissing", cfEx.Faults[0].Code, "Expected content missing fault");

              // Test review with bad properties; first try bad book id; if book id is invalid, controller rejects immediately
              var dummyReview = new BookReview() { BookId = Guid.NewGuid(), Rating = 10 };
              //Should return ObjectNotFound (book not found);
              cfEx = TestUtil.ExpectClientFault(() => client.ExecutePost<BookReview, BookReview>(dummyReview, reviewUpdateUrl));
              Assert.AreEqual(1, cfEx.Faults.Count, "Should be a single fault.");
              var fault0 = cfEx.Faults[0];
              Assert.IsTrue(fault0.Code == "ObjectNotFound" && fault0.Tag == "BookId");

              // Make new review with bad properties and try to post
              var testReview = new BookReview() { BookId = csBk.Id, Rating = 10, Caption = null, Review = new string('?', 1500)};
              cfEx = TestUtil.ExpectClientFault(() => client.ExecutePost<BookReview, BookReview>(testReview, reviewUpdateUrl));
              // Now we should get multiple faults: Rating out of range, caption may not be null, Review text too long
              /*  Here's BadRequest response body:
               [{"Code":"ValueMissing","Message":"Caption may not be empty.","Tag":"Caption","Path":null,"Parameters":{}},
            {"Code":"ValueTooLong","Message":"Review text is too long, must be under 1000 chars","Tag":"Review","Path":null,"Parameters":{}},
            {"Code":"ValueOutOfRange","Message":"Rating must be between 1 and 5","Tag":"Rating","Path":null,"Parameters":{"InvalidValue":"10"}}]
              */
              Assert.AreEqual(3, cfEx.Faults.Count, "Expected 3 faults");
              Assert.IsTrue(cfEx.Faults[0].Code == "ValueMissing" && cfEx.Faults[0].Tag == "Caption", "Expected Caption fault");
              Assert.IsTrue(cfEx.Faults[1].Code == "ValueTooLong" && cfEx.Faults[1].Tag == "Review", "Expected Review too long fault");
              Assert.IsTrue(cfEx.Faults[2].Code == "ValueOutOfRange" && cfEx.Faults[2].Tag == "Rating", "Expected Rating out of range fault");
              Logout();

              // Test invalid URL path, no match to controller method --------------------------------------------------------------------------
              // nullref method accepts GET only
              var badUrlExc = TestUtil.ExpectFailWith<ClientFaultException>(() => client.ExecutePost<object, string>(null, "api/special/nullref"));
              Assert.AreEqual(ClientFaultCodes.InvalidUrlOrMethod, badUrlExc.Faults[0].Code, "Expected InvalidUrlOrMethod code.");

              // test malformed parameters ------------------------------------------------------------------------------------------------------
              // Check bad parameter type handling
              // p1 should be int, p2 is Guid; we expect BadRequest with 2 faults
              var cfExc = TestUtil.ExpectFailWith<ClientFaultException>(() => client.ExecuteGet<string>("api/special/foo/{0}/{1}", "not-int", "not-Guid"));
              Assert.AreEqual(2, cfExc.Faults.Count, "Expected 2 faults");
        }
Пример #10
0
        public void TestUserReviews()
        {
            var client = SetupHelper.Client;
              var csBk = client.ExecuteGet<SearchResults<Book>>("api/books?title={0}", "c#").Results[0];
              //get details - with reviews
              var csBkDet = client.ExecuteGet<Book>("api/books/{0}", csBk.Id);
              Assert.IsNotNull(csBkDet, "Failed to get c# book details.");
              //check reviews are returned
              Assert.IsTrue(csBkDet.LatestReviews.Count > 0, "Reviews not returned");
              //get review by id
              var reviewId = csBkDet.LatestReviews[0].Id;
              var review = client.ExecuteGet<BookReview>("api/reviews/{0}", reviewId);
              Assert.IsNotNull(review, "Failed to get review");

              //Let's login as Diego and post a review for cs book
              var diegoReview = new BookReview() { BookId = csBk.Id, Rating = 2, Caption = "Not impressed", Review = "Outdated, boring" };
              LoginAs("Diego");
              diegoReview = client.ExecutePost<BookReview, BookReview>(diegoReview, "api/user/reviews");
              Assert.IsNotNull(diegoReview, "Failed to post review");
              Assert.IsTrue(diegoReview.Id != Guid.Empty, "Expected non-empty review ID.");
              var diegoReviewId = diegoReview.Id;
              //Diego changes rating
              diegoReview.Rating = 1;
              client.ExecutePut<BookReview, BookReview>(diegoReview, "api/user/reviews");
              // let's read it back and check rating
              diegoReview = client.ExecuteGet<BookReview>("api/reviews/{0}", diegoReview.Id);
              Assert.AreEqual(1, diegoReview.Rating, "Expected rating 1.");

              //Delete it
              var status = client.ExecuteDelete("api/user/reviews/{0}", diegoReviewId);
              Assert.AreEqual(HttpStatusCode.NoContent, status, "Failed to delete.");
              // Try to read it back - should be null
              diegoReview = client.ExecuteGet<BookReview>("api/reviews/{0}", diegoReviewId);
              Assert.IsNull(diegoReview, "Failed to delete review.");
              //Try to delete it again - should get ObjectNotFound
              var cfExc = TestUtil.ExpectClientFault(() => client.ExecuteDelete("api/user/reviews/{0}", diegoReviewId));
              Assert.AreEqual(ClientFaultCodes.ObjectNotFound, cfExc.Faults[0].Code, "Expected object not found fault");

              Logout();
        }