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; }
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); }
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)); }
public BookReview UpdateReview(BookReview review) { return(CreateUpdateReview(review, create: false)); }
public BookReview AddReview(BookReview review) { return(CreateUpdateReview(review, create: true)); }
public BookReview AddReview(BookReview review) { return CreateUpdateReview(review, create: true); }
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); }
public BookReview UpdateReview(BookReview review) { return CreateUpdateReview(review, create: false); }
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"); }
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(); }