diff --git a/CHANGELOG.md b/CHANGELOG.md index 775f3248c9..94358ae8c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features +- User Feedback can now be captured without errors/exceptions. Note that these APIs replace the older UserFeedback APIs, which have now been marked as obsolete (and will be removed in a future major version bump) ([#3981](https://github.com/getsentry/sentry-dotnet/pull/3981)) - Users can now register their own MAUI controls for breadcrumb creation ([#3997](https://github.com/getsentry/sentry-dotnet/pull/3997)) - Serilog scope properties are now sent with Sentry events ([#3976](https://github.com/getsentry/sentry-dotnet/pull/3976)) - The sample seed used for sampling decisions is now propagated, for use in downstream custom trace samplers ([#3951](https://github.com/getsentry/sentry-dotnet/pull/3951)) diff --git a/samples/Sentry.Samples.AspNetCore.Mvc/Controllers/HomeController.cs b/samples/Sentry.Samples.AspNetCore.Mvc/Controllers/HomeController.cs index de18940dd7..ef3a27275b 100644 --- a/samples/Sentry.Samples.AspNetCore.Mvc/Controllers/HomeController.cs +++ b/samples/Sentry.Samples.AspNetCore.Mvc/Controllers/HomeController.cs @@ -1,6 +1,7 @@ using System.Data; using System.Diagnostics; using Microsoft.AspNetCore.Mvc; +using Samples.AspNetCore.Mvc.Models; using Sentry.Ben.BlockingDetector; using Sentry.Samples.AspNetCore.Mvc.Models; @@ -176,4 +177,33 @@ public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } + + [HttpGet("[controller]/feedback")] + public IActionResult Feedback() + { + return View(); + } + + [HttpPost] + public async Task SubmitFeedback(FeedbackModel feedback) + { + if (!ModelState.IsValid) + { + return View("Feedback", feedback); + } + + var sentryFeedback = new SentryFeedback(feedback.Message!, feedback.ContactEmail, feedback.Name); + var hint = new SentryHint(); + + if (feedback.Screenshot is { Length: > 0 }) + { + await using var memoryStream = new MemoryStream(); + await feedback.Screenshot.CopyToAsync(memoryStream); + hint.AddAttachment(memoryStream.ToArray(), feedback.Screenshot.FileName, AttachmentType.Default, "image/png"); + } + + SentrySdk.CaptureFeedback(sentryFeedback, null, hint); + ViewBag.Message = "Feedback submitted successfully!"; + return View("Index"); + } } diff --git a/samples/Sentry.Samples.AspNetCore.Mvc/Models/FeedbackModel.cs b/samples/Sentry.Samples.AspNetCore.Mvc/Models/FeedbackModel.cs new file mode 100644 index 0000000000..00dfba0ca3 --- /dev/null +++ b/samples/Sentry.Samples.AspNetCore.Mvc/Models/FeedbackModel.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Samples.AspNetCore.Mvc.Models; + +public class FeedbackModel +{ + [Required] + public string? Message { get; set; } + + [EmailAddress] + public string? ContactEmail { get; set; } + + public string? Name { get; set; } + + public IFormFile? Screenshot { get; set; } +} diff --git a/samples/Sentry.Samples.AspNetCore.Mvc/Sentry.Samples.AspNetCore.Mvc.csproj b/samples/Sentry.Samples.AspNetCore.Mvc/Sentry.Samples.AspNetCore.Mvc.csproj index b2b958bf3c..d3bbf0aa34 100644 --- a/samples/Sentry.Samples.AspNetCore.Mvc/Sentry.Samples.AspNetCore.Mvc.csproj +++ b/samples/Sentry.Samples.AspNetCore.Mvc/Sentry.Samples.AspNetCore.Mvc.csproj @@ -18,4 +18,8 @@ + + + + diff --git a/samples/Sentry.Samples.AspNetCore.Mvc/Views/Home/Feedback.cshtml b/samples/Sentry.Samples.AspNetCore.Mvc/Views/Home/Feedback.cshtml new file mode 100644 index 0000000000..1534eda1c8 --- /dev/null +++ b/samples/Sentry.Samples.AspNetCore.Mvc/Views/Home/Feedback.cshtml @@ -0,0 +1,36 @@ +@model Samples.AspNetCore.Mvc.Models.FeedbackModel + +@{ + ViewData["Title"] = "Submit Feedback"; +} + +

Submit Feedback

+ +@if (ViewBag.Message != null) +{ +
@ViewBag.Message
+} + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+ +
diff --git a/samples/Sentry.Samples.AspNetCore.Mvc/Views/Shared/_Layout.cshtml b/samples/Sentry.Samples.AspNetCore.Mvc/Views/Shared/_Layout.cshtml index a10ed1f464..6de93829f5 100644 --- a/samples/Sentry.Samples.AspNetCore.Mvc/Views/Shared/_Layout.cshtml +++ b/samples/Sentry.Samples.AspNetCore.Mvc/Views/Shared/_Layout.cshtml @@ -31,6 +31,9 @@ + diff --git a/samples/Sentry.Samples.Console.Customized/Program.cs b/samples/Sentry.Samples.Console.Customized/Program.cs index f85ae49da6..dac1d9062a 100644 --- a/samples/Sentry.Samples.Console.Customized/Program.cs +++ b/samples/Sentry.Samples.Console.Customized/Program.cs @@ -142,12 +142,18 @@ await SentrySdk.ConfigureScopeAsync(async scope => var eventId = SentrySdk.CaptureMessage("Some warning!", SentryLevel.Warning); - // Send an user feedback linked to the warning. + // Send feedback linked to the warning. var timestamp = DateTime.Now.Ticks; var user = $"user{timestamp}"; var email = $"user{timestamp}@user{timestamp}.com"; - - SentrySdk.CaptureUserFeedback(new UserFeedback(eventId, user, email, "this is a sample user feedback")); + SentrySdk.CaptureFeedback(new SentryFeedback( + message: "this is a sample user feedback", + contactEmail: email, + name: user, + replayId: null, + url: null, + associatedEventId: eventId + )); var error = new Exception("Attempting to send this multiple times"); diff --git a/samples/Sentry.Samples.Maui/MainPage.xaml b/samples/Sentry.Samples.Maui/MainPage.xaml index d1519f610c..672b9d2347 100644 --- a/samples/Sentry.Samples.Maui/MainPage.xaml +++ b/samples/Sentry.Samples.Maui/MainPage.xaml @@ -70,6 +70,13 @@ Clicked="OnNativeCrashClicked" HorizontalOptions="Center" /> +