diff --git a/README.md b/README.md
index 1b4ec1d73c..838d92caab 100644
--- a/README.md
+++ b/README.md
@@ -135,9 +135,6 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github.
Real-time communication
SMS send and receive
-
- Voice over IP (VoIP)
-
### Contacts and calendar
diff --git a/Samples/3DPrinting/cppwinrt/Package.appxmanifest b/Samples/3DPrinting/cppwinrt/Package.appxmanifest
index 429ce22abd..aff4106b9d 100644
--- a/Samples/3DPrinting/cppwinrt/Package.appxmanifest
+++ b/Samples/3DPrinting/cppwinrt/Package.appxmanifest
@@ -8,7 +8,7 @@
- _3DPrinting C++/WinRT Sample
+ 3DPrinting C++/WinRT Sample
Microsoft Corporation
Assets\storelogo-sdk.png
@@ -21,10 +21,10 @@
diff --git a/Samples/3DPrinting/cppwinrt/Scenario1_Print.cpp b/Samples/3DPrinting/cppwinrt/Scenario1_Print.cpp
index e1956584ef..d425bb6420 100644
--- a/Samples/3DPrinting/cppwinrt/Scenario1_Print.cpp
+++ b/Samples/3DPrinting/cppwinrt/Scenario1_Print.cpp
@@ -30,10 +30,7 @@ namespace
#pragma region Buffer, stream, and string helpers
void SetBufferBytes(IBuffer const& buffer, void const* data, uint32_t size)
{
- byte* bytes;
- auto byteAccess = buffer.as<::Windows::Storage::Streams::IBufferByteAccess>();
- winrt::check_hresult(byteAccess->Buffer(&bytes));
- memcpy_s(bytes, buffer.Length(), data, size);
+ memcpy_s(buffer.data(), buffer.Length(), data, size);
}
IAsyncOperation StreamToStringAsync(IRandomAccessStream stream)
diff --git a/Samples/3DPrinting/cppwinrt/Scenario2_Launch.cpp b/Samples/3DPrinting/cppwinrt/Scenario2_Launch.cpp
index dca9461b27..f4c2ad7499 100644
--- a/Samples/3DPrinting/cppwinrt/Scenario2_Launch.cpp
+++ b/Samples/3DPrinting/cppwinrt/Scenario2_Launch.cpp
@@ -31,6 +31,8 @@ namespace winrt::SDKTemplate::implementation
fire_and_forget Scenario2_Launch::CheckIf3DBuilderIsInstalled_Click(IInspectable const&, RoutedEventArgs const&)
{
+ auto lifetime = get_strong();
+
IVectorView handlers = co_await Launcher::FindFileHandlersAsync(L".3mf");
auto found = std::find_if(begin(handlers), end(handlers),
[](auto&& info) { return info.PackageFamilyName() == PackageFamilyName3DBuilder; });
diff --git a/Samples/3DPrinting/cppwinrt/pch.h b/Samples/3DPrinting/cppwinrt/pch.h
index c0ac0228be..2328ff869b 100644
--- a/Samples/3DPrinting/cppwinrt/pch.h
+++ b/Samples/3DPrinting/cppwinrt/pch.h
@@ -23,4 +23,3 @@
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Media.h"
#include "winrt/Windows.UI.Xaml.Navigation.h"
-#include
diff --git a/Samples/BasicFaceDetection/README.md b/Samples/BasicFaceDetection/README.md
index b676c1a989..476ec789fc 100644
--- a/Samples/BasicFaceDetection/README.md
+++ b/Samples/BasicFaceDetection/README.md
@@ -3,8 +3,7 @@ page_type: sample
languages:
- csharp
- cpp
-- cppcx
-- vb
+- cppwinrt
products:
- windows
- windows-uwp
@@ -56,6 +55,8 @@ The FaceDetector is intended to operate on a static image or a single frame of v
### Samples
+[BasicFaceDetection](/archived/BasicFaceTracking) for C++/CX and VB (archived)
+
[BasicFaceTracking](/Samples/BasicFaceTracking)
[HolographicFaceTracking](/Samples/HolographicFaceTracking)
diff --git a/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.sln b/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.sln
new file mode 100644
index 0000000000..071327890d
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29920.165
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicFaceDetection", "BasicFaceDetection.vcxproj", "{03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|ARM.ActiveCfg = Debug|ARM
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|ARM.Build.0 = Debug|ARM
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|ARM.Deploy.0 = Debug|ARM
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|x64.ActiveCfg = Debug|x64
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|x64.Build.0 = Debug|x64
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|x64.Deploy.0 = Debug|x64
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|x86.ActiveCfg = Debug|Win32
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|x86.Build.0 = Debug|Win32
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Debug|x86.Deploy.0 = Debug|Win32
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|ARM.ActiveCfg = Release|ARM
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|ARM.Build.0 = Release|ARM
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|ARM.Deploy.0 = Release|ARM
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|x64.ActiveCfg = Release|x64
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|x64.Build.0 = Release|x64
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|x64.Deploy.0 = Release|x64
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|x86.ActiveCfg = Release|Win32
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|x86.Build.0 = Release|Win32
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B13F3350-3448-4B3D-B219-BDE8EF55A27E}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.vcxproj b/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.vcxproj
new file mode 100644
index 0000000000..b97e70d6be
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.vcxproj
@@ -0,0 +1,188 @@
+
+
+
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), LICENSE))\SharedContent
+
+
+ true
+ {03FE0C00-0A0D-58F2-AAB1-AA9014D5DF4D}
+ BasicFaceDetection
+ SDKTemplate
+ en-US
+ 15.0
+ true
+ Windows Store
+ 10.0
+ 10.0.18362.0
+ $(WindowsTargetPlatformVersion)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);$(SharedContentDir)\cppwinrt
+ true
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ 4453;28204
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+ ..\shared\Scenario1_DetectInPhoto.xaml
+
+
+ ..\shared\Scenario2_DetectInWebcam.xaml
+
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+ SampleConfiguration.h
+
+
+ ..\shared\Scenario1_DetectInPhoto.xaml
+
+
+ ..\shared\Scenario2_DetectInWebcam.xaml
+
+
+ Create
+ pch.h
+
+
+ Project.idl
+
+
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.vcxproj.filters b/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.vcxproj.filters
new file mode 100644
index 0000000000..1ddb709a19
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/BasicFaceDetection.vcxproj.filters
@@ -0,0 +1,63 @@
+
+
+
+
+ 4416d50a-7676-4d0a-9b2c-91ff70c6047f
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/BasicFaceDetection/cppwinrt/Package.appxmanifest b/Samples/BasicFaceDetection/cppwinrt/Package.appxmanifest
new file mode 100644
index 0000000000..96950dec2a
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/Package.appxmanifest
@@ -0,0 +1,42 @@
+
+
+
+
+
+ BasicFaceDetection C++/WinRT Sample
+ Microsoft Corporation
+ Assets\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/BasicFaceDetection/cppwinrt/Project.idl b/Samples/BasicFaceDetection/cppwinrt/Project.idl
new file mode 100644
index 0000000000..d3a1c66ed6
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/Project.idl
@@ -0,0 +1,25 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+namespace SDKTemplate
+{
+ [default_interface]
+ runtimeclass Scenario1_DetectInPhoto : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario1_DetectInPhoto();
+ }
+
+ [default_interface]
+ runtimeclass Scenario2_DetectInWebcam : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario2_DetectInWebcam();
+ }
+}
diff --git a/Samples/BasicFaceDetection/cppwinrt/SampleConfiguration.cpp b/Samples/BasicFaceDetection/cppwinrt/SampleConfiguration.cpp
new file mode 100644
index 0000000000..2378c63efb
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/SampleConfiguration.cpp
@@ -0,0 +1,99 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include
+#include "MainPage.h"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Graphics::Imaging;
+using namespace winrt::Windows::Media::FaceAnalysis;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::UI::Xaml::Media::Imaging;
+using namespace winrt::SDKTemplate;
+
+hstring implementation::MainPage::FEATURE_NAME()
+{
+ return L"Face detection C++/WinRT sample";
+}
+
+IVector implementation::MainPage::scenariosInner = winrt::single_threaded_observable_vector(
+{
+ Scenario{ L"Detect Faces in Photos", xaml_typename() },
+ Scenario{ L"Detect Faces in Webcam", xaml_typename() },
+});
+
+// Rescale the size and position of the face highlight
+// to account for the difference between the size of the image and
+// the canvas.
+void ApplyScale(FrameworkElement const& box, double widthScale, double heightScale)
+{
+ // We saved the original size of the face box in the element's Tag field.
+ BitmapBounds faceBox = unbox_value(box.Tag());
+ box.Width(faceBox.Width * widthScale);
+ box.Height(faceBox.Height * heightScale);
+ box.Margin({ faceBox.X * widthScale, faceBox.Y * heightScale, 0, 0 });
+}
+
+void SampleHelpers::HighlightFaces(
+ WriteableBitmap const& displaySource,
+ IVector const& foundFaces,
+ Canvas const& canvas,
+ DataTemplate const& dataTemplate)
+{
+
+ double widthScale = canvas.ActualWidth() / displaySource.PixelWidth();
+ double heightScale = canvas.ActualHeight() / displaySource.PixelHeight();
+
+ for (DetectedFace face : foundFaces)
+ {
+ // Create an element for displaying the face box but since we're using a Canvas
+ // we must scale the elements according to the image's actual size.
+ // The original FaceBox values are saved in the element's Tag field so we can update the
+ // boxes when the Canvas is resized.
+ FrameworkElement box = dataTemplate.LoadContent().as();
+ box.Tag(box_value(face.FaceBox()));
+ ApplyScale(box, widthScale, heightScale);
+ canvas.Children().Append(box);
+ }
+
+ hstring message;
+ int32_t faceCount = foundFaces.Size();
+ if (faceCount == 0)
+ {
+ message = L"Didn't find any human faces in the image";
+ }
+ else if (faceCount == 1)
+ {
+ message = L"Found a human face in the image";
+ }
+ else
+ {
+ message = L"Found " + to_hstring(faceCount) + L" human faces in the image";
+ }
+
+ MainPage::Current().NotifyUser(message, NotifyType::StatusMessage);
+
+}
+
+void SampleHelpers::RepositionFaces(WriteableBitmap const& displaySource, Canvas const& canvas)
+{
+ double widthScale = canvas.ActualWidth() / displaySource.PixelWidth();
+ double heightScale = canvas.ActualHeight() / displaySource.PixelHeight();
+
+ for (UIElement element : canvas.Children())
+ {
+ ApplyScale(element.as(), widthScale, heightScale);
+ }
+}
diff --git a/Samples/BasicFaceDetection/cppwinrt/SampleConfiguration.h b/Samples/BasicFaceDetection/cppwinrt/SampleConfiguration.h
new file mode 100644
index 0000000000..3bdb020c07
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/SampleConfiguration.h
@@ -0,0 +1,25 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace winrt::SDKTemplate::SampleHelpers
+{
+ void HighlightFaces(
+ Windows::UI::Xaml::Media::Imaging::WriteableBitmap const& displaySource,
+ Windows::Foundation::Collections::IVector const& foundFaces,
+ Windows::UI::Xaml::Controls::Canvas const& canvas,
+ Windows::UI::Xaml::DataTemplate const& dataTemplate);
+ void RepositionFaces(
+ Windows::UI::Xaml::Media::Imaging::WriteableBitmap const& displaySource,
+ Windows::UI::Xaml::Controls::Canvas const& canvas);
+}
diff --git a/Samples/BasicFaceDetection/cppwinrt/Scenario1_DetectInPhoto.cpp b/Samples/BasicFaceDetection/cppwinrt/Scenario1_DetectInPhoto.cpp
new file mode 100644
index 0000000000..9bbf7e3b19
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/Scenario1_DetectInPhoto.cpp
@@ -0,0 +1,156 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario1_DetectInPhoto.h"
+#include "Scenario1_DetectInPhoto.g.cpp"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Graphics::Imaging;
+using namespace winrt::Windows::Media::FaceAnalysis;
+using namespace winrt::Windows::Storage;
+using namespace winrt::Windows::Storage::Pickers;
+using namespace winrt::Windows::Storage::Streams;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Media;
+using namespace winrt::Windows::UI::Xaml::Media::Imaging;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario1_DetectInPhoto::Scenario1_DetectInPhoto()
+ {
+ InitializeComponent();
+ }
+
+ // Takes the photo image and FaceDetector results and assembles the visualization onto the Canvas.
+ //
+ // displaySource is a bitmap object holding the image we're going to display.
+ // foundFaces is a list of detected faces; output from FaceDetector.
+ void Scenario1_DetectInPhoto::SetupVisualization(WriteableBitmap const& displaySource, IVector const& foundFaces)
+ {
+ ImageBrush brush;
+ brush.ImageSource(displaySource);
+ brush.Stretch(Stretch::Fill);
+ PhotoCanvas().Background(brush);
+
+ SampleHelpers::HighlightFaces(displaySource, foundFaces, PhotoCanvas(), HighlightedFaceBox());
+ }
+
+ // Clears the display of image and face boxes.
+ void Scenario1_DetectInPhoto::ClearVisualization()
+ {
+ PhotoCanvas().Background(nullptr);
+ PhotoCanvas().Children().Clear();
+ rootPage.NotifyUser(L"", NotifyType::StatusMessage);
+ }
+
+ // Computes a BitmapTransform to downscale the source image if it's too large.
+ //
+ // Performance of the FaceDetector degrades significantly with large images, and in most cases it's best to downscale
+ // the source bitmaps if they're too large before passing them into FaceDetector. Remember through, your application's performance needs will vary.
+ BitmapTransform Scenario1_DetectInPhoto::ComputeScalingTransformForSourceImage(BitmapDecoder const& sourceDecoder)
+ {
+ BitmapTransform transform;
+
+ uint32_t sourceHeight = sourceDecoder.PixelHeight();
+ if (sourceHeight > sourceImageHeightLimit)
+ {
+ double scalingFactor = (double)sourceImageHeightLimit / sourceHeight;
+
+ transform.ScaledWidth((uint32_t)(sourceDecoder.PixelWidth() * scalingFactor));
+ transform.ScaledHeight((uint32_t)(sourceHeight * scalingFactor));
+ }
+
+ return transform;
+ }
+
+ // Loads an image file (selected by the user) and runs the FaceDetector on the loaded bitmap. If successful calls SetupVisualization to display the results.
+ fire_and_forget Scenario1_DetectInPhoto::OpenFile_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ FileOpenPicker photoPicker;
+ photoPicker.ViewMode(PickerViewMode::Thumbnail);
+ photoPicker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
+ photoPicker.FileTypeFilter().ReplaceAll({ L".jpg", L".jpeg", L".png", L".bmp" });
+
+ StorageFile photoFile = co_await photoPicker.PickSingleFileAsync();
+ if (photoFile == nullptr)
+ {
+ co_return;
+ }
+
+ ClearVisualization();
+ rootPage.NotifyUser(L"Opening...", NotifyType::StatusMessage);
+
+ try
+ {
+ // Open the image file and decode the bitmap into memory.
+ // We'll need to make 2 bitmap copies: one for the FaceDetector and another to display.
+ IRandomAccessStream fileStream = co_await photoFile.OpenAsync(FileAccessMode::Read);
+ {
+ BitmapDecoder decoder = co_await BitmapDecoder::CreateAsync(fileStream);
+ BitmapTransform transform = ComputeScalingTransformForSourceImage(decoder);
+
+ SoftwareBitmap originalBitmap = co_await decoder.GetSoftwareBitmapAsync(decoder.BitmapPixelFormat(), BitmapAlphaMode::Ignore, transform, ExifOrientationMode::IgnoreExifOrientation, ColorManagementMode::DoNotColorManage);
+
+ // We need to convert the image into a format that's compatible with FaceDetector.
+ // Gray8 should be a good type but verify it against FaceDetector’s supported formats.
+ static constexpr BitmapPixelFormat InputPixelFormat = BitmapPixelFormat::Gray8;
+ if (FaceDetector::IsBitmapPixelFormatSupported(InputPixelFormat))
+ {
+ SoftwareBitmap detectorInput = SoftwareBitmap::Convert(originalBitmap, InputPixelFormat);
+
+ // Create a WritableBitmap for our visualization display; copy the original bitmap pixels to wb's buffer.
+ WriteableBitmap displaySource(originalBitmap.PixelWidth(), originalBitmap.PixelHeight());
+ originalBitmap.CopyToBuffer(displaySource.PixelBuffer());
+
+ rootPage.NotifyUser(L"Detecting...", NotifyType::StatusMessage);
+
+ // Initialize our FaceDetector and execute it against our input image.
+ // NOTE: FaceDetector initialization can take a long time, and in most cases
+ // you should create a member variable and reuse the object.
+ // However, for simplicity in this scenario we instantiate a new instance each time.
+ FaceDetector detector = co_await FaceDetector::CreateAsync();
+ IVector faces = co_await detector.DetectFacesAsync(detectorInput);
+
+ // Create our display using the available image and face results.
+ SetupVisualization(displaySource, faces);
+ }
+ else
+ {
+ rootPage.NotifyUser(L"PixelFormat 'Gray8' is not supported by FaceDetector", NotifyType::ErrorMessage);
+ }
+ }
+ }
+ catch (hresult_error const& ex)
+ {
+ ClearVisualization();
+ rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);
+ }
+ }
+
+ // Updates any existing face bounding boxes in response to changes in the size of the Canvas.
+ void Scenario1_DetectInPhoto::PhotoCanvas_SizeChanged(IInspectable const&, SizeChangedEventArgs const&)
+ {
+ // If the Canvas is resized we must recompute a new scaling factor and
+ // apply it to each face box.
+ ImageBrush brush = PhotoCanvas().Background().try_as();
+ if (brush != nullptr)
+ {
+ WriteableBitmap displaySource = brush.ImageSource().as();
+ SampleHelpers::RepositionFaces(displaySource, PhotoCanvas());
+ }
+ }
+}
diff --git a/Samples/BasicFaceDetection/cppwinrt/Scenario1_DetectInPhoto.h b/Samples/BasicFaceDetection/cppwinrt/Scenario1_DetectInPhoto.h
new file mode 100644
index 0000000000..d46e303e13
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/Scenario1_DetectInPhoto.h
@@ -0,0 +1,48 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario1_DetectInPhoto.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario1_DetectInPhoto : Scenario1_DetectInPhotoT
+ {
+ Scenario1_DetectInPhoto();
+
+ fire_and_forget OpenFile_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void PhotoCanvas_SizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+
+ // Limit on the height of the source image (in pixels) passed into FaceDetector for performance considerations.
+ // Images larger that this size will be downscaled proportionally.
+ //
+ // This is an arbitrary value that was chosen for this scenario, in which FaceDetector performance isn't too important but face
+ // detection accuracy is; a generous size is used.
+ // Your application may have different performance and accuracy needs and you'll need to decide how best to control input.
+ static constexpr uint32_t sourceImageHeightLimit = 1280;
+
+ void SetupVisualization(Windows::UI::Xaml::Media::Imaging::WriteableBitmap const& displaySource, Windows::Foundation::Collections::IVector const& foundFaces);
+ void ClearVisualization();
+ Windows::Graphics::Imaging::BitmapTransform ComputeScalingTransformForSourceImage(Windows::Graphics::Imaging::BitmapDecoder const& sourceDecoder);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario1_DetectInPhoto : Scenario1_DetectInPhotoT
+ {
+ };
+}
diff --git a/Samples/BasicFaceDetection/cppwinrt/Scenario2_DetectInWebcam.cpp b/Samples/BasicFaceDetection/cppwinrt/Scenario2_DetectInWebcam.cpp
new file mode 100644
index 0000000000..797fcbdc86
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/Scenario2_DetectInWebcam.cpp
@@ -0,0 +1,307 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario2_DetectInWebcam.h"
+#include "Scenario2_DetectInWebcam.g.cpp"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::Windows::ApplicationModel;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Graphics::Imaging;
+using namespace winrt::Windows::Media;
+using namespace winrt::Windows::Media::Capture;
+using namespace winrt::Windows::Media::FaceAnalysis;
+using namespace winrt::Windows::Media::MediaProperties;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Media;
+using namespace winrt::Windows::UI::Xaml::Media::Imaging;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario2_DetectInWebcam::Scenario2_DetectInWebcam()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario2_DetectInWebcam::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ suspendingEventToken = Application::Current().Suspending({ get_weak(), &Scenario2_DetectInWebcam::OnSuspending });
+ }
+
+ void Scenario2_DetectInWebcam::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ Application::Current().Suspending(suspendingEventToken);
+ }
+
+ // Responds to App Suspend event to stop/release MediaCapture object if it's running and return to Idle state.
+ fire_and_forget Scenario2_DetectInWebcam::OnSuspending(IInspectable const&, SuspendingEventArgs const& e)
+ {
+ auto lifetime = get_strong();
+
+ if (currentState == ScenarioState::Streaming)
+ {
+ auto deferral = e.SuspendingOperation().GetDeferral();
+ co_await ChangeScenarioStateAsync(ScenarioState::Idle);
+ deferral.Complete();
+ }
+ }
+
+ // Creates the FaceDetector object which we will use for face detection.
+ // Initializes a new MediaCapture instance and starts the Preview streaming to the CamPreview UI element.
+ // Completes with true if initialization and streaming were successful and false if an exception occurred.
+ IAsyncOperation Scenario2_DetectInWebcam::StartWebcamStreamingAsync()
+ {
+ auto lifetime = get_strong();
+
+ bool successful;
+
+ faceDetector = co_await FaceDetector::CreateAsync();
+ try
+ {
+ MediaCapture mediaCapture;
+ agileMediaCapture = mediaCapture;
+ MediaCaptureInitializationSettings settings;
+
+ // For this scenario, we only need Video (not microphone) so specify this in the initializer.
+ // NOTE: the appxmanifest only declares "webcam" under capabilities and if this is changed to include
+ // microphone (default constructor) you must add "microphone" to the manifest or initialization will fail.
+ settings.StreamingCaptureMode(StreamingCaptureMode::Video);
+
+ co_await mediaCapture.InitializeAsync(settings);
+ mediaCapture.CameraStreamStateChanged({ get_weak(), &Scenario2_DetectInWebcam::MediaCapture_CameraStreamStateChanged });
+
+ // Cache the media properties as we'll need them later.
+ auto deviceController = mediaCapture.VideoDeviceController();
+ videoProperties = deviceController.GetMediaStreamProperties(MediaStreamType::VideoPreview).as();
+
+ // Immediately start streaming to our CaptureElement UI.
+ // NOTE: CaptureElement's Source must be set before streaming is started.
+ CamPreview().Source(mediaCapture);
+ co_await mediaCapture.StartPreviewAsync();
+
+ successful = true;
+ }
+ catch (hresult_access_denied const&)
+ {
+ // If the user has disabled their webcam this exception is thrown; provide a descriptive message to inform the user of this fact.
+ rootPage.NotifyUser(L"Webcam is disabled or access to the webcam is disabled for this app.\nEnsure Privacy Settings allow webcam usage.", NotifyType::ErrorMessage);
+ successful = false;
+ }
+ catch (hresult_error const& ex)
+ {
+ rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);
+ successful = false;
+ }
+
+ co_return successful;
+ }
+
+ // Safely stops webcam streaming (if running) and releases MediaCapture object.
+ IAsyncAction Scenario2_DetectInWebcam::ShutdownWebcamAsync()
+ {
+ auto lifetime = get_strong();
+
+ if (agileMediaCapture)
+ {
+ auto mediaCapture = agileMediaCapture.get();
+ if (mediaCapture.CameraStreamState() == Windows::Media::Devices::CameraStreamState::Streaming)
+ {
+ try
+ {
+ co_await mediaCapture.StopPreviewAsync();
+ }
+ catch (hresult_error const&)
+ {
+ // Since we're going to destroy the MediaCapture object there's nothing to do here
+ }
+ }
+ mediaCapture.Close();
+ }
+
+ CamPreview().Source(nullptr);
+ agileMediaCapture = nullptr;
+ }
+
+ // Captures a single frame from the running webcam stream and executes the FaceDetector on the image. If successful calls SetupVisualization to display the results.
+ IAsyncOperation Scenario2_DetectInWebcam::TakeSnapshotAndFindFacesAsync()
+ {
+ auto lifetime = get_strong();
+
+ if (currentState != ScenarioState::Streaming)
+ {
+ co_return false;
+ }
+
+ bool successful = false;
+
+ try
+ {
+ // Create a VideoFrame object specifying the pixel format we want our capture image to be (NV12 bitmap in this case).
+ // GetPreviewFrame will convert the native webcam frame into this format.
+ static constexpr BitmapPixelFormat InputPixelFormat = BitmapPixelFormat::Nv12;
+ VideoFrame previewFrame(InputPixelFormat, (int)videoProperties.Width(), (int)videoProperties.Height());
+
+ co_await agileMediaCapture.get().GetPreviewFrameAsync(previewFrame);
+
+ // The returned VideoFrame should be in the supported NV12 format but we need to verify
+ if (FaceDetector::IsBitmapPixelFormatSupported(previewFrame.SoftwareBitmap().BitmapPixelFormat()))
+ {
+ IVector faces = co_await faceDetector.DetectFacesAsync(previewFrame.SoftwareBitmap());
+
+ // Create a WritableBitmap for our visualization display; copy the original bitmap pixels to wb's buffer.
+ // Note that WriteableBitmap doesn't support NV12 and we have to convert it to 32-bit BGRA.
+ SoftwareBitmap convertedSource = SoftwareBitmap::Convert(previewFrame.SoftwareBitmap(), BitmapPixelFormat::Bgra8);
+ WriteableBitmap displaySource(convertedSource.PixelWidth(), convertedSource.PixelHeight());
+ convertedSource.CopyToBuffer(displaySource.PixelBuffer());
+
+ // Create our display using the available image and face results.
+ SetupVisualization(displaySource, faces);
+
+ successful = true;
+ }
+ else
+ {
+ rootPage.NotifyUser(L"PixelFormat 'NV12' is not supported by FaceDetector", NotifyType::ErrorMessage);
+ }
+ }
+ catch (hresult_error const& ex)
+ {
+ rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);
+ }
+
+ co_return successful;
+ }
+
+ // Takes the webcam image and FaceTracker results and assembles the visualization onto the Canvas.
+ void Scenario2_DetectInWebcam::SetupVisualization(WriteableBitmap const& displaySource, IVector const& foundFaces)
+ {
+ ImageBrush brush;
+ brush.ImageSource(displaySource);
+ brush.Stretch(Stretch::Fill);
+ SnapshotCanvas().Background(brush);
+
+ SampleHelpers::HighlightFaces(displaySource, foundFaces, SnapshotCanvas(), HighlightedFaceBox());
+ }
+
+ // Manages the scenario's internal state. Invokes the internal methods and updates the UI according to the
+ // passed in state value. Handles failures and resets the state if necessary.
+ IAsyncAction Scenario2_DetectInWebcam::ChangeScenarioStateAsync(ScenarioState newState)
+ {
+ auto lifetime = get_strong();
+
+ switch (newState)
+ {
+ case ScenarioState::Idle:
+
+ CameraSnapshotButton().IsEnabled(false);
+ currentState = newState;
+ co_await ShutdownWebcamAsync();
+
+ SnapshotCanvas().Background(nullptr);
+ SnapshotCanvas().Children().Clear();
+ CameraStreamingButton().Content(box_value(L"Start Streaming"));
+ CameraSnapshotButton().Content(box_value(L"Take Snapshot"));
+ break;
+
+ case ScenarioState::Streaming:
+
+ if (!co_await StartWebcamStreamingAsync())
+ {
+ co_await ChangeScenarioStateAsync(ScenarioState::Idle);
+ break;
+ }
+
+ SnapshotCanvas().Background(nullptr);
+ SnapshotCanvas().Children().Clear();
+ CameraSnapshotButton().IsEnabled(true);
+ CameraStreamingButton().Content(box_value(L"Stop Streaming"));
+ CameraSnapshotButton().Content(box_value(L"Take Snapshot"));
+ currentState = newState;
+ break;
+
+ case ScenarioState::Snapshot:
+
+ if (!co_await TakeSnapshotAndFindFacesAsync())
+ {
+ co_await ChangeScenarioStateAsync(ScenarioState::Idle);
+ break;
+ }
+
+ co_await ShutdownWebcamAsync();
+
+ CameraSnapshotButton().IsEnabled(true);
+ CameraStreamingButton().Content(box_value(L"Start Streaming"));
+ CameraSnapshotButton().Content(box_value(L"Clear Display"));
+ currentState = newState;
+ break;
+ }
+ }
+
+ // Handles MediaCapture changes by shutting down streaming and returning to Idle state.
+ fire_and_forget Scenario2_DetectInWebcam::MediaCapture_CameraStreamStateChanged(MediaCapture const&, IInspectable const& args)
+ {
+ auto lifetime = get_strong();
+
+ // MediaCapture is not Agile and so we cannot invoke it's methods on this caller's thread
+ // and instead need to schedule the state change on the UI thread.
+ co_await resume_foreground(Dispatcher());
+ co_await ChangeScenarioStateAsync(ScenarioState::Idle);
+ }
+
+ // Handles "streaming" button clicks to start/stop webcam streaming.
+ fire_and_forget Scenario2_DetectInWebcam::CameraStreamingButton_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ rootPage.NotifyUser(L"", NotifyType::StatusMessage);
+ if (currentState == ScenarioState::Streaming)
+ {
+ co_await ChangeScenarioStateAsync(ScenarioState::Idle);
+ }
+ else
+ {
+ co_await ChangeScenarioStateAsync(ScenarioState::Streaming);
+ }
+ }
+
+ // Handles "snapshot" button clicks to take a snapshot or clear the current display.
+ fire_and_forget Scenario2_DetectInWebcam::CameraSnapshotButton_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ rootPage.NotifyUser(L"", NotifyType::StatusMessage);
+ if (currentState == ScenarioState::Streaming)
+ {
+ co_await ChangeScenarioStateAsync(ScenarioState::Snapshot);
+ }
+ else
+ {
+ co_await ChangeScenarioStateAsync(ScenarioState::Idle);
+ }
+ }
+
+ // Updates any existing face bounding boxes in response to changes in the size of the Canvas.
+ void Scenario2_DetectInWebcam::SnapshotCanvas_SizeChanged(IInspectable const&, SizeChangedEventArgs const&)
+ {
+ // If the Canvas is resized we must recompute a new scaling factor and
+ // apply it to each face box.
+ ImageBrush brush = SnapshotCanvas().Background().try_as();
+ if (brush != nullptr)
+ {
+ WriteableBitmap displaySource = brush.ImageSource().as();
+ SampleHelpers::RepositionFaces(displaySource, SnapshotCanvas());
+ }
+ }
+}
diff --git a/Samples/BasicFaceDetection/cppwinrt/Scenario2_DetectInWebcam.h b/Samples/BasicFaceDetection/cppwinrt/Scenario2_DetectInWebcam.h
new file mode 100644
index 0000000000..89a353cd8e
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/Scenario2_DetectInWebcam.h
@@ -0,0 +1,81 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario2_DetectInWebcam.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario2_DetectInWebcam : Scenario2_DetectInWebcamT
+ {
+ Scenario2_DetectInWebcam();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget CameraStreamingButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ fire_and_forget CameraSnapshotButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void SnapshotCanvas_SizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
+
+ private:
+ // Values for identifying and controlling scenario states.
+ enum ScenarioState
+ {
+ // Display is blank - default state.
+ Idle,
+
+ // Webcam is actively engaged and a live video stream is displayed.
+ Streaming,
+
+ // Snapshot image has been captured and is being displayed along with detected faces; webcam is not active.
+ Snapshot,
+ };
+
+ private:
+ // Reference back to the "root" page of the app.
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+
+ // Holds the current scenario state value.
+ ScenarioState currentState = ScenarioState::Idle;
+
+ // References a MediaCapture instance; is null when not in Streaming state.
+ agile_ref agileMediaCapture{ nullptr };
+
+ // Cache of properties from the current MediaCapture device which is used for capturing the preview frame.
+ Windows::Media::MediaProperties::VideoEncodingProperties videoProperties{ nullptr };
+
+ // References a FaceDetector instance.
+ Windows::Media::FaceAnalysis::FaceDetector faceDetector{ nullptr };
+
+ // Event registration tokens.
+ event_token suspendingEventToken;
+
+ private:
+ fire_and_forget OnSuspending(Windows::Foundation::IInspectable const& sender, Windows::ApplicationModel::SuspendingEventArgs const& e);
+ Windows::Foundation::IAsyncOperation StartWebcamStreamingAsync();
+ Windows::Foundation::IAsyncAction ShutdownWebcamAsync();
+ Windows::Foundation::IAsyncOperation TakeSnapshotAndFindFacesAsync();
+ void SetupVisualization(Windows::UI::Xaml::Media::Imaging::WriteableBitmap const& displaySource, Windows::Foundation::Collections::IVector const& foundFaces);
+ Windows::Foundation::IAsyncAction ChangeScenarioStateAsync(ScenarioState newState);
+ fire_and_forget AbandonStreaming();
+ fire_and_forget MediaCapture_CameraStreamStateChanged(Windows::Media::Capture::MediaCapture const& sender, Windows::Foundation::IInspectable const& args);
+
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario2_DetectInWebcam : Scenario2_DetectInWebcamT
+ {
+ };
+}
diff --git a/SharedContent/Templates/UWPSDKSampleCPP/packages.config b/Samples/BasicFaceDetection/cppwinrt/packages.config
similarity index 59%
rename from SharedContent/Templates/UWPSDKSampleCPP/packages.config
rename to Samples/BasicFaceDetection/cppwinrt/packages.config
index 605fbab91d..3b87ab00fd 100644
--- a/SharedContent/Templates/UWPSDKSampleCPP/packages.config
+++ b/Samples/BasicFaceDetection/cppwinrt/packages.config
@@ -1,4 +1,4 @@

-
+
\ No newline at end of file
diff --git a/Samples/BasicFaceDetection/cppwinrt/pch.cpp b/Samples/BasicFaceDetection/cppwinrt/pch.cpp
new file mode 100644
index 0000000000..01484ff5aa
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/pch.cpp
@@ -0,0 +1,6 @@
+//
+// pch.cpp
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/BasicFaceDetection/cppwinrt/pch.h b/Samples/BasicFaceDetection/cppwinrt/pch.h
new file mode 100644
index 0000000000..986d2c64b4
--- /dev/null
+++ b/Samples/BasicFaceDetection/cppwinrt/pch.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+#include "winrt/Windows.Foundation.h"
+#include "winrt/Windows.Foundation.Collections.h"
+#include "winrt/Windows.ApplicationModel.h"
+#include "winrt/Windows.ApplicationModel.Activation.h"
+#include "winrt/Windows.Graphics.Imaging.h"
+#include "winrt/Windows.Media.h"
+#include "winrt/Windows.Media.Capture.h"
+#include "winrt/Windows.Media.Devices.h"
+#include "winrt/Windows.Media.FaceAnalysis.h"
+#include "winrt/Windows.Media.MediaProperties.h"
+#include "winrt/Windows.Storage.h"
+#include "winrt/Windows.Storage.Pickers.h"
+#include "winrt/Windows.Storage.Streams.h"
+#include "winrt/Windows.System.h"
+#include "winrt/Windows.UI.Core.h"
+#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.UI.Xaml.Automation.Peers.h"
+#include "winrt/Windows.UI.Xaml.Controls.h"
+#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
+#include "winrt/Windows.UI.Xaml.Documents.h"
+#include "winrt/Windows.UI.Xaml.Interop.h"
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.Xaml.Media.h"
+#include "winrt/Windows.UI.Xaml.Media.Imaging.h"
+#include "winrt/Windows.UI.Xaml.Navigation.h"
diff --git a/Samples/BasicFaceDetection/cs/Package.appxmanifest b/Samples/BasicFaceDetection/cs/Package.appxmanifest
index de6c292a7b..4974f0195e 100644
--- a/Samples/BasicFaceDetection/cs/Package.appxmanifest
+++ b/Samples/BasicFaceDetection/cs/Package.appxmanifest
@@ -48,7 +48,6 @@
-
\ No newline at end of file
diff --git a/Samples/BasicFaceDetection/cs/SampleConfiguration.cs b/Samples/BasicFaceDetection/cs/SampleConfiguration.cs
index 7892a44c6d..37785539d6 100644
--- a/Samples/BasicFaceDetection/cs/SampleConfiguration.cs
+++ b/Samples/BasicFaceDetection/cs/SampleConfiguration.cs
@@ -11,7 +11,11 @@
using System;
using System.Collections.Generic;
+using Windows.Graphics.Imaging;
+using Windows.Media.FaceAnalysis;
+using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media.Imaging;
namespace SDKTemplate
{
@@ -21,9 +25,72 @@ public partial class MainPage : Page
List scenarios = new List
{
- new Scenario() { Title="Detect Faces in Photos", ClassType=typeof(DetectFacesInPhoto)},
- new Scenario() { Title="Detect Faces in Webcam", ClassType=typeof(DetectFacesInWebcam)},
+ new Scenario() { Title="Detect Faces in Photos", ClassType=typeof(Scenario1_DetectInPhoto)},
+ new Scenario() { Title="Detect Faces in Webcam", ClassType=typeof(Scenario2_DetectInWebcam)},
};
+
+ ///
+ /// Rescale the size and position of the face highlight box
+ /// to account for the difference between the size of the image and
+ /// the canvas.
+ ///
+ /// The element to rescale
+ /// Horizontal adjustment factor
+ /// Vertical adjustment factor
+ static void ApplyScale(FrameworkElement box, double widthScale, double heightScale)
+ {
+ // We saved the original size of the face box in the element's Tag field.
+ BitmapBounds faceBox = (BitmapBounds)box.Tag;
+ box.Width = faceBox.Width * widthScale;
+ box.Height = faceBox.Height * heightScale;
+ box.Margin = new Thickness(faceBox.X * widthScale, faceBox.Y * heightScale, 0, 0);
+ }
+
+ public static void HighlightFaces(WriteableBitmap displaySource, IList foundFaces, Canvas canvas, DataTemplate template)
+ {
+ double widthScale = canvas.ActualWidth / displaySource.PixelWidth;
+ double heightScale = canvas.ActualHeight / displaySource.PixelHeight;
+
+ foreach (DetectedFace face in foundFaces)
+ {
+ // Create an element for displaying the face box but since we're using a Canvas
+ // we must scale it according to the image's actual size.
+ // The original FaceBox values are saved in the element's Tag field so we can update the
+ // boxes when the Canvas is resized.
+ var box = (FrameworkElement)template.LoadContent();
+ box.Tag = face.FaceBox;
+ ApplyScale(box, widthScale, heightScale);
+
+ canvas.Children.Add(box);
+ }
+
+ string message;
+ if (foundFaces.Count == 0)
+ {
+ message = "Didn't find any human faces in the image";
+ }
+ else if (foundFaces.Count == 1)
+ {
+ message = "Found a human face in the image";
+ }
+ else
+ {
+ message = "Found " + foundFaces.Count + " human faces in the image";
+ }
+
+ MainPage.Current.NotifyUser(message, NotifyType.StatusMessage);
+ }
+
+ public static void RepositionFaces(WriteableBitmap displaySource, Canvas canvas)
+ {
+ double widthScale = canvas.ActualWidth / displaySource.PixelWidth;
+ double heightScale = canvas.ActualHeight / displaySource.PixelHeight;
+
+ foreach (var item in canvas.Children)
+ {
+ ApplyScale((FrameworkElement)item, widthScale, heightScale);
+ }
+ }
}
public class Scenario
diff --git a/Samples/BasicFaceDetection/cs/Scenario1_DetectInPhoto.xaml.cs b/Samples/BasicFaceDetection/cs/Scenario1_DetectInPhoto.xaml.cs
index 0e1178d284..32176a936b 100644
--- a/Samples/BasicFaceDetection/cs/Scenario1_DetectInPhoto.xaml.cs
+++ b/Samples/BasicFaceDetection/cs/Scenario1_DetectInPhoto.xaml.cs
@@ -22,14 +22,13 @@
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
-using Windows.UI.Xaml.Shapes;
namespace SDKTemplate
{
///
/// Page for demonstrating FaceDetection on an image file.
///
- public sealed partial class DetectFacesInPhoto : Page
+ public sealed partial class Scenario1_DetectInPhoto : Page
{
///
/// Brush for drawing the bounding box around each detected face.
@@ -63,9 +62,9 @@ public sealed partial class DetectFacesInPhoto : Page
private MainPage rootPage;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- public DetectFacesInPhoto()
+ public Scenario1_DetectInPhoto()
{
this.InitializeComponent();
}
@@ -86,50 +85,8 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
/// List of detected faces; output from FaceDetector
private void SetupVisualization(WriteableBitmap displaySource, IList foundFaces)
{
- ImageBrush brush = new ImageBrush();
- brush.ImageSource = displaySource;
- brush.Stretch = Stretch.Fill;
- this.PhotoCanvas.Background = brush;
-
- if (foundFaces != null)
- {
- double widthScale = displaySource.PixelWidth / this.PhotoCanvas.ActualWidth;
- double heightScale = displaySource.PixelHeight / this.PhotoCanvas.ActualHeight;
-
- foreach (DetectedFace face in foundFaces)
- {
- // Create a rectangle element for displaying the face box but since we're using a Canvas
- // we must scale the rectangles according to the image’s actual size.
- // The original FaceBox values are saved in the Rectangle's Tag field so we can update the
- // boxes when the Canvas is resized.
- Rectangle box = new Rectangle();
- box.Tag = face.FaceBox;
- box.Width = (uint)(face.FaceBox.Width / widthScale);
- box.Height = (uint)(face.FaceBox.Height / heightScale);
- box.Fill = this.fillBrush;
- box.Stroke = this.lineBrush;
- box.StrokeThickness = this.lineThickness;
- box.Margin = new Thickness((uint)(face.FaceBox.X / widthScale), (uint)(face.FaceBox.Y / heightScale), 0, 0);
-
- this.PhotoCanvas.Children.Add(box);
- }
- }
-
- string message;
- if (foundFaces == null || foundFaces.Count == 0)
- {
- message = "Didn't find any human faces in the image";
- }
- else if (foundFaces.Count == 1)
- {
- message = "Found a human face in the image";
- }
- else
- {
- message = "Found " + foundFaces.Count + " human faces in the image";
- }
-
- this.rootPage.NotifyUser(message, NotifyType.StatusMessage);
+ this.PhotoCanvas.Background = new ImageBrush() { ImageSource = displaySource, Stretch = Stretch.Fill };
+ MainPage.HighlightFaces(displaySource, foundFaces, this.PhotoCanvas, this.HighlightedFaceBox);
}
///
@@ -173,36 +130,31 @@ private BitmapTransform ComputeScalingTransformForSourceImage(BitmapDecoder sour
/// Event data
private async void OpenFile_Click(object sender, RoutedEventArgs e)
{
- IList faces = null;
- SoftwareBitmap detectorInput = null;
- WriteableBitmap displaySource = null;
-
- try
+ FileOpenPicker photoPicker = new FileOpenPicker();
+ photoPicker.ViewMode = PickerViewMode.Thumbnail;
+ photoPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
+ photoPicker.FileTypeFilter.Add(".jpg");
+ photoPicker.FileTypeFilter.Add(".jpeg");
+ photoPicker.FileTypeFilter.Add(".png");
+ photoPicker.FileTypeFilter.Add(".bmp");
+
+ StorageFile photoFile = await photoPicker.PickSingleFileAsync();
+ if (photoFile == null)
{
- FileOpenPicker photoPicker = new FileOpenPicker();
- photoPicker.ViewMode = PickerViewMode.Thumbnail;
- photoPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
- photoPicker.FileTypeFilter.Add(".jpg");
- photoPicker.FileTypeFilter.Add(".jpeg");
- photoPicker.FileTypeFilter.Add(".png");
- photoPicker.FileTypeFilter.Add(".bmp");
-
- StorageFile photoFile = await photoPicker.PickSingleFileAsync();
- if (photoFile == null)
- {
- return;
- }
+ return;
+ }
- this.ClearVisualization();
- this.rootPage.NotifyUser("Opening...", NotifyType.StatusMessage);
+ this.ClearVisualization();
+ this.rootPage.NotifyUser("Opening...", NotifyType.StatusMessage);
+ try
+ {
// Open the image file and decode the bitmap into memory.
// We'll need to make 2 bitmap copies: one for the FaceDetector and another to display.
using (IRandomAccessStream fileStream = await photoFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
BitmapTransform transform = this.ComputeScalingTransformForSourceImage(decoder);
-
using (SoftwareBitmap originalBitmap = await decoder.GetSoftwareBitmapAsync(decoder.BitmapPixelFormat, BitmapAlphaMode.Ignore, transform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage))
{
// We need to convert the image into a format that's compatible with FaceDetector.
@@ -210,10 +162,10 @@ private async void OpenFile_Click(object sender, RoutedEventArgs e)
const BitmapPixelFormat InputPixelFormat = BitmapPixelFormat.Gray8;
if (FaceDetector.IsBitmapPixelFormatSupported(InputPixelFormat))
{
- using (detectorInput = SoftwareBitmap.Convert(originalBitmap, InputPixelFormat))
+ using (SoftwareBitmap detectorInput = SoftwareBitmap.Convert(originalBitmap, InputPixelFormat))
{
- // Create a WritableBitmap for our visualization display; copy the original bitmap pixels to wb's buffer.
- displaySource = new WriteableBitmap(originalBitmap.PixelWidth, originalBitmap.PixelHeight);
+ // Create a WritableBitmap for our visualization display; copy the original bitmap pixels to WriteableBitmap's buffer.
+ WriteableBitmap displaySource = new WriteableBitmap(originalBitmap.PixelWidth, originalBitmap.PixelHeight);
originalBitmap.CopyToBuffer(displaySource.PixelBuffer);
this.rootPage.NotifyUser("Detecting...", NotifyType.StatusMessage);
@@ -223,7 +175,7 @@ private async void OpenFile_Click(object sender, RoutedEventArgs e)
// you should create a member variable and reuse the object.
// However, for simplicity in this scenario we instantiate a new instance each time.
FaceDetector detector = await FaceDetector.CreateAsync();
- faces = await detector.DetectFacesAsync(detectorInput);
+ IList faces = await detector.DetectFacesAsync(detectorInput);
// Create our display using the available image and face results.
this.SetupVisualization(displaySource, faces);
@@ -250,37 +202,12 @@ private async void OpenFile_Click(object sender, RoutedEventArgs e)
/// Event data
private void PhotoCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
- try
- {
- // If the Canvas is resized we must recompute a new scaling factor and
- // apply it to each face box.
- if (this.PhotoCanvas.Background != null)
- {
- WriteableBitmap displaySource = (this.PhotoCanvas.Background as ImageBrush).ImageSource as WriteableBitmap;
-
- double widthScale = displaySource.PixelWidth / this.PhotoCanvas.ActualWidth;
- double heightScale = displaySource.PixelHeight / this.PhotoCanvas.ActualHeight;
-
- foreach (var item in PhotoCanvas.Children)
- {
- Rectangle box = item as Rectangle;
- if (box == null)
- {
- continue;
- }
-
- // We saved the original size of the face box in the rectangles Tag field.
- BitmapBounds faceBounds = (BitmapBounds)box.Tag;
- box.Width = (uint)(faceBounds.Width / widthScale);
- box.Height = (uint)(faceBounds.Height / heightScale);
-
- box.Margin = new Thickness((uint)(faceBounds.X / widthScale), (uint)(faceBounds.Y / heightScale), 0, 0);
- }
- }
- }
- catch (Exception ex)
+ // If the Canvas is resized we must recompute a new scaling factor and
+ // apply it to each face box.
+ ImageBrush brush = (ImageBrush)this.PhotoCanvas.Background;
+ if (brush != null)
{
- this.rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
+ MainPage.RepositionFaces((WriteableBitmap)brush.ImageSource, this.PhotoCanvas);
}
}
}
diff --git a/Samples/BasicFaceDetection/cs/Scenario2_DetectInWebcam.xaml.cs b/Samples/BasicFaceDetection/cs/Scenario2_DetectInWebcam.xaml.cs
index a3328597d5..40d52f2dbf 100644
--- a/Samples/BasicFaceDetection/cs/Scenario2_DetectInWebcam.xaml.cs
+++ b/Samples/BasicFaceDetection/cs/Scenario2_DetectInWebcam.xaml.cs
@@ -12,7 +12,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-
+using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Media.Capture;
@@ -23,34 +23,18 @@
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
-using Windows.UI.Xaml.Shapes;
namespace SDKTemplate
{
///
/// Page for demonstrating FaceDetection on a webcam snapshot.
///
- public sealed partial class DetectFacesInWebcam : Page
+ public sealed partial class Scenario2_DetectInWebcam : Page
{
- ///
- /// Brush for drawing the bounding box around each detected face.
- ///
- private readonly SolidColorBrush lineBrush = new SolidColorBrush(Windows.UI.Colors.Yellow);
-
- ///
- /// Thickness of the face bounding box lines.
- ///
- private readonly double lineThickness = 2.0;
-
- ///
- /// Transparent fill for the bounding box.
- ///
- private readonly SolidColorBrush fillBrush = new SolidColorBrush(Windows.UI.Colors.Transparent);
-
///
/// Reference back to the "root" page of the app.
///
- private MainPage rootPage;
+ private MainPage rootPage = MainPage.Current;
///
/// Holds the current scenario state value.
@@ -73,14 +57,13 @@ public sealed partial class DetectFacesInWebcam : Page
private FaceDetector faceDetector;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- public DetectFacesInWebcam()
+ public Scenario2_DetectInWebcam()
{
this.InitializeComponent();
this.currentState = ScenarioState.Idle;
- App.Current.Suspending += this.OnSuspending;
}
///
@@ -105,19 +88,21 @@ private enum ScenarioState
}
///
- /// Responds when we navigate to this page.
+ /// Called when we navigate to this page.
///
/// Event data
- protected override async void OnNavigatedTo(NavigationEventArgs e)
+ protected override void OnNavigatedTo(NavigationEventArgs e)
{
- this.rootPage = MainPage.Current;
+ App.Current.Suspending += this.OnSuspending;
+ }
- // The 'await' operation can only be used from within an async method but class constructors
- // cannot be labeled as async, and so we'll initialize FaceDetector here.
- if (this.faceDetector == null)
- {
- this.faceDetector = await FaceDetector.CreateAsync();
- }
+ ///
+ /// Called when we navigate away from this page.
+ ///
+ /// Event data
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ App.Current.Suspending -= this.OnSuspending;
}
///
@@ -125,14 +110,14 @@ protected override async void OnNavigatedTo(NavigationEventArgs e)
///
/// The source of the Suspending event
/// Event data
- private void OnSuspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
+ private async void OnSuspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
{
if (this.currentState == ScenarioState.Streaming)
{
var deferral = e.SuspendingOperation.GetDeferral();
try
{
- this.ChangeScenarioState(ScenarioState.Idle);
+ await this.ChangeScenarioStateAsync(ScenarioState.Idle);
}
finally
{
@@ -145,9 +130,11 @@ private void OnSuspending(object sender, Windows.ApplicationModel.SuspendingEven
/// Initializes a new MediaCapture instance and starts the Preview streaming to the CamPreview UI element.
///
/// Async Task object returning true if initialization and streaming were successful and false if an exception occurred.
- private async Task StartWebcamStreaming()
+ private async Task StartWebcamStreamingAsync()
{
- bool successful = true;
+ bool successful = false;
+
+ this.faceDetector = await FaceDetector.CreateAsync();
try
{
@@ -169,17 +156,17 @@ private async Task StartWebcamStreaming()
// NOTE: CaptureElement's Source must be set before streaming is started.
this.CamPreview.Source = this.mediaCapture;
await this.mediaCapture.StartPreviewAsync();
+
+ successful = true;
}
catch (System.UnauthorizedAccessException)
{
// If the user has disabled their webcam this exception is thrown; provide a descriptive message to inform the user of this fact.
this.rootPage.NotifyUser("Webcam is disabled or access to the webcam is disabled for this app.\nEnsure Privacy Settings allow webcam usage.", NotifyType.ErrorMessage);
- successful = false;
}
catch (Exception ex)
{
this.rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
- successful = false;
}
return successful;
@@ -188,7 +175,7 @@ private async Task StartWebcamStreaming()
///
/// Safely stops webcam streaming (if running) and releases MediaCapture object.
///
- private async void ShutdownWebCam()
+ private async Task ShutdownWebcamAsync()
{
if (this.mediaCapture != null)
{
@@ -208,20 +195,17 @@ private async void ShutdownWebCam()
/// Captures a single frame from the running webcam stream and executes the FaceDetector on the image. If successful calls SetupVisualization to display the results.
///
/// Async Task object returning true if the capture was successful and false if an exception occurred.
- private async Task TakeSnapshotAndFindFaces()
+ private async Task TakeSnapshotAndFindFacesAsync()
{
- bool successful = true;
-
- try
+ if (this.currentState != ScenarioState.Streaming)
{
- if (this.currentState != ScenarioState.Streaming)
- {
- return false;
- }
+ return false;
+ }
- WriteableBitmap displaySource = null;
- IList faces = null;
+ bool successful = false;
+ try
+ {
// Create a VideoFrame object specifying the pixel format we want our capture image to be (NV12 bitmap in this case).
// GetPreviewFrame will convert the native webcam frame into this format.
const BitmapPixelFormat InputPixelFormat = BitmapPixelFormat.Nv12;
@@ -232,23 +216,26 @@ private async Task TakeSnapshotAndFindFaces()
// The returned VideoFrame should be in the supported NV12 format but we need to verify this.
if (FaceDetector.IsBitmapPixelFormatSupported(previewFrame.SoftwareBitmap.BitmapPixelFormat))
{
- faces = await this.faceDetector.DetectFacesAsync(previewFrame.SoftwareBitmap);
+ IList faces = await this.faceDetector.DetectFacesAsync(previewFrame.SoftwareBitmap);
+
+ // Create a WritableBitmap for our visualization display; copy the original bitmap pixels to wb's buffer.
+ // Note that WriteableBitmap doesn't support NV12 and we have to convert it to 32-bit BGRA.
+ WriteableBitmap displaySource;
+ using (SoftwareBitmap convertedSource = SoftwareBitmap.Convert(previewFrame.SoftwareBitmap, BitmapPixelFormat.Bgra8))
+ {
+ displaySource = new WriteableBitmap(convertedSource.PixelWidth, convertedSource.PixelHeight);
+ convertedSource.CopyToBuffer(displaySource.PixelBuffer);
+ }
+
+ // Create our display using the available image and face results.
+ this.SetupVisualization(displaySource, faces);
+
+ successful = true;
}
else
{
this.rootPage.NotifyUser("PixelFormat '" + InputPixelFormat.ToString() + "' is not supported by FaceDetector", NotifyType.ErrorMessage);
}
-
- // Create a WritableBitmap for our visualization display; copy the original bitmap pixels to wb's buffer.
- // Note that WriteableBitmap doesn't support NV12 and we have to convert it to 32-bit BGRA.
- using (SoftwareBitmap convertedSource = SoftwareBitmap.Convert(previewFrame.SoftwareBitmap, BitmapPixelFormat.Bgra8))
- {
- displaySource = new WriteableBitmap(convertedSource.PixelWidth, convertedSource.PixelHeight);
- convertedSource.CopyToBuffer(displaySource.PixelBuffer);
- }
-
- // Create our display using the available image and face results.
- this.SetupVisualization(displaySource, faces);
}
}
catch (Exception ex)
@@ -267,50 +254,8 @@ private async Task TakeSnapshotAndFindFaces()
/// List of detected faces; output from FaceDetector
private void SetupVisualization(WriteableBitmap displaySource, IList foundFaces)
{
- ImageBrush brush = new ImageBrush();
- brush.ImageSource = displaySource;
- brush.Stretch = Stretch.Fill;
- this.SnapshotCanvas.Background = brush;
-
- if (foundFaces != null)
- {
- double widthScale = displaySource.PixelWidth / this.SnapshotCanvas.ActualWidth;
- double heightScale = displaySource.PixelHeight / this.SnapshotCanvas.ActualHeight;
-
- foreach (DetectedFace face in foundFaces)
- {
- // Create a rectangle element for displaying the face box but since we're using a Canvas
- // we must scale the rectangles according to the image's actual size.
- // The original FaceBox values are saved in the Rectangle's Tag field so we can update the
- // boxes when the Canvas is resized.
- Rectangle box = new Rectangle();
- box.Tag = face.FaceBox;
- box.Width = (uint)(face.FaceBox.Width / widthScale);
- box.Height = (uint)(face.FaceBox.Height / heightScale);
- box.Fill = this.fillBrush;
- box.Stroke = this.lineBrush;
- box.StrokeThickness = this.lineThickness;
- box.Margin = new Thickness((uint)(face.FaceBox.X / widthScale), (uint)(face.FaceBox.Y / heightScale), 0, 0);
-
- this.SnapshotCanvas.Children.Add(box);
- }
- }
-
- string message;
- if (foundFaces == null || foundFaces.Count == 0)
- {
- message = "Didn't find any human faces in the image";
- }
- else if (foundFaces.Count == 1)
- {
- message = "Found a human face in the image";
- }
- else
- {
- message = "Found " + foundFaces.Count + " human faces in the image";
- }
-
- this.rootPage.NotifyUser(message, NotifyType.StatusMessage);
+ this.SnapshotCanvas.Background = new ImageBrush() { ImageSource = displaySource, Stretch = Stretch.Fill };
+ MainPage.HighlightFaces(displaySource, foundFaces, this.SnapshotCanvas, this.HighlightedFaceBox);
}
///
@@ -318,17 +263,17 @@ private void SetupVisualization(WriteableBitmap displaySource, IList
/// State to switch to
- private async void ChangeScenarioState(ScenarioState newState)
+ private async Task ChangeScenarioStateAsync(ScenarioState newState)
{
switch (newState)
{
case ScenarioState.Idle:
- this.ShutdownWebCam();
+ this.CameraSnapshotButton.IsEnabled = false;
+ await this.ShutdownWebcamAsync();
this.SnapshotCanvas.Background = null;
this.SnapshotCanvas.Children.Clear();
- this.CameraSnapshotButton.IsEnabled = false;
this.CameraStreamingButton.Content = "Start Streaming";
this.CameraSnapshotButton.Content = "Take Snapshot";
this.currentState = newState;
@@ -336,9 +281,9 @@ private async void ChangeScenarioState(ScenarioState newState)
case ScenarioState.Streaming:
- if (!await this.StartWebcamStreaming())
+ if (!await this.StartWebcamStreamingAsync())
{
- this.ChangeScenarioState(ScenarioState.Idle);
+ await this.ChangeScenarioStateAsync(ScenarioState.Idle);
break;
}
@@ -352,13 +297,13 @@ private async void ChangeScenarioState(ScenarioState newState)
case ScenarioState.Snapshot:
- if (!await this.TakeSnapshotAndFindFaces())
+ if (!await this.TakeSnapshotAndFindFacesAsync())
{
- this.ChangeScenarioState(ScenarioState.Idle);
+ await this.ChangeScenarioStateAsync(ScenarioState.Idle);
break;
}
- this.ShutdownWebCam();
+ await this.ShutdownWebcamAsync();
this.CameraSnapshotButton.IsEnabled = true;
this.CameraStreamingButton.Content = "Start Streaming";
@@ -373,13 +318,13 @@ private async void ChangeScenarioState(ScenarioState newState)
///
/// The source of the event, i.e. our MediaCapture object
/// Event data
- private void MediaCapture_CameraStreamStateChanged(MediaCapture sender, object args)
+ private async void MediaCapture_CameraStreamStateChanged(MediaCapture sender, object args)
{
- // MediaCapture is not Agile and so we cannot invoke it's methods on this caller's thread
+ // MediaCapture is not Agile and so we cannot invoke its methods on this caller's thread
// and instead need to schedule the state change on the UI thread.
- var ignored = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
- ChangeScenarioState(ScenarioState.Idle);
+ await ChangeScenarioStateAsync(ScenarioState.Idle);
});
}
@@ -388,17 +333,16 @@ private void MediaCapture_CameraStreamStateChanged(MediaCapture sender, object a
///
/// Button user clicked
/// Event data
- private void CameraStreamingButton_Click(object sender, RoutedEventArgs e)
+ private async void CameraStreamingButton_Click(object sender, RoutedEventArgs e)
{
+ this.rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
if (this.currentState == ScenarioState.Streaming)
{
- this.rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
- this.ChangeScenarioState(ScenarioState.Idle);
+ await this.ChangeScenarioStateAsync(ScenarioState.Idle);
}
else
{
- this.rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
- this.ChangeScenarioState(ScenarioState.Streaming);
+ await this.ChangeScenarioStateAsync(ScenarioState.Streaming);
}
}
@@ -407,17 +351,16 @@ private void CameraStreamingButton_Click(object sender, RoutedEventArgs e)
///
/// Button user clicked
/// Event data
- private void CameraSnapshotButton_Click(object sender, RoutedEventArgs e)
+ private async void CameraSnapshotButton_Click(object sender, RoutedEventArgs e)
{
+ this.rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
if (this.currentState == ScenarioState.Streaming)
{
- this.rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
- this.ChangeScenarioState(ScenarioState.Snapshot);
+ await this.ChangeScenarioStateAsync(ScenarioState.Snapshot);
}
else
{
- this.rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
- this.ChangeScenarioState(ScenarioState.Idle);
+ await this.ChangeScenarioStateAsync(ScenarioState.Idle);
}
}
@@ -428,37 +371,12 @@ private void CameraSnapshotButton_Click(object sender, RoutedEventArgs e)
/// Event data
private void SnapshotCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
- try
+ // If the Canvas is resized we must recompute a new scaling factor and
+ // apply it to each face box.
+ ImageBrush brush = (ImageBrush)this.SnapshotCanvas.Background;
+ if (brush != null)
{
- // If the Canvas is resized we must recompute a new scaling factor and
- // apply it to each face box.
- if (this.currentState == ScenarioState.Snapshot && this.SnapshotCanvas.Background != null)
- {
- WriteableBitmap displaySource = (this.SnapshotCanvas.Background as ImageBrush).ImageSource as WriteableBitmap;
-
- double widthScale = displaySource.PixelWidth / this.SnapshotCanvas.ActualWidth;
- double heightScale = displaySource.PixelHeight / this.SnapshotCanvas.ActualHeight;
-
- foreach (var item in this.SnapshotCanvas.Children)
- {
- Rectangle box = item as Rectangle;
- if (box == null)
- {
- continue;
- }
-
- // We saved the original size of the face box in the rectangles Tag field.
- BitmapBounds faceBounds = (BitmapBounds)box.Tag;
- box.Width = (uint)(faceBounds.Width / widthScale);
- box.Height = (uint)(faceBounds.Height / heightScale);
-
- box.Margin = new Thickness((uint)(faceBounds.X / widthScale), (uint)(faceBounds.Y / heightScale), 0, 0);
- }
- }
- }
- catch (Exception ex)
- {
- this.rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
+ MainPage.RepositionFaces((WriteableBitmap)brush.ImageSource, this.SnapshotCanvas);
}
}
}
diff --git a/Samples/BasicFaceDetection/shared/Scenario1_DetectInPhoto.xaml b/Samples/BasicFaceDetection/shared/Scenario1_DetectInPhoto.xaml
index 7f90a7eb24..93efa8bb8c 100644
--- a/Samples/BasicFaceDetection/shared/Scenario1_DetectInPhoto.xaml
+++ b/Samples/BasicFaceDetection/shared/Scenario1_DetectInPhoto.xaml
@@ -11,7 +11,7 @@
//*********************************************************
-->
+
+
+
+
+
+
@@ -44,11 +50,6 @@
-
-
-
-
diff --git a/Samples/BasicFaceDetection/shared/Scenario2_DetectInWebcam.xaml b/Samples/BasicFaceDetection/shared/Scenario2_DetectInWebcam.xaml
index 596451310e..0b574522d6 100644
--- a/Samples/BasicFaceDetection/shared/Scenario2_DetectInWebcam.xaml
+++ b/Samples/BasicFaceDetection/shared/Scenario2_DetectInWebcam.xaml
@@ -12,7 +12,7 @@
-->
+
+
+
+
+
+
@@ -49,10 +55,6 @@
-
-
-
diff --git a/Samples/BasicFaceTracking/cppwinrt/Scenario1_TrackInWebcam.cpp b/Samples/BasicFaceTracking/cppwinrt/Scenario1_TrackInWebcam.cpp
index 57fba5c99a..e550c35a47 100644
--- a/Samples/BasicFaceTracking/cppwinrt/Scenario1_TrackInWebcam.cpp
+++ b/Samples/BasicFaceTracking/cppwinrt/Scenario1_TrackInWebcam.cpp
@@ -51,6 +51,8 @@ namespace winrt::SDKTemplate::implementation
// Responds to App Suspend event to stop/release MediaCapture object if it's running and return to Idle state.
fire_and_forget Scenario1_TrackInWebcam::OnSuspending(IInspectable const&, SuspendingEventArgs const& e)
{
+ auto lifetime = get_strong();
+
if (currentState == ScenarioState::Streaming)
{
auto deferral = e.SuspendingOperation().GetDeferral();
@@ -116,6 +118,8 @@ namespace winrt::SDKTemplate::implementation
// Safely stops webcam streaming (if running) and releases MediaCapture object.
IAsyncAction Scenario1_TrackInWebcam::ShutdownWebcamAsync()
{
+ auto lifetime = get_strong();
+
if (frameProcessingTimer != nullptr)
{
frameProcessingTimer.Cancel();
@@ -171,6 +175,8 @@ namespace winrt::SDKTemplate::implementation
IAsyncAction Scenario1_TrackInWebcam::ProcessCurrentVideoFrameAsync()
{
+ auto lifetime = get_strong();
+
// Create a VideoFrame object specifying the pixel format we want our capture image to be (NV12 bitmap in this case).
// GetPreviewFrame will convert the native webcam frame into this format.
static constexpr BitmapPixelFormat InputPixelFormat = BitmapPixelFormat::Nv12;
@@ -245,6 +251,8 @@ namespace winrt::SDKTemplate::implementation
IAsyncAction Scenario1_TrackInWebcam::ChangeScenarioStateAsync(ScenarioState newState)
{
+ auto lifetime = get_strong();
+
// Disable UI while state change is in progress
CameraStreamingButton().IsEnabled(false);
@@ -277,6 +285,8 @@ namespace winrt::SDKTemplate::implementation
fire_and_forget Scenario1_TrackInWebcam::AbandonStreaming()
{
+ auto lifetime = get_strong();
+
// MediaCapture is not Agile and so we cannot invoke its methods on this caller's thread
// and instead need to schedule the state change on the UI thread.
co_await resume_foreground(Dispatcher());
@@ -291,6 +301,8 @@ namespace winrt::SDKTemplate::implementation
// Handles "streaming" button clicks to start/stop webcam streaming.
fire_and_forget Scenario1_TrackInWebcam::CameraStreamingButton_Click(IInspectable const&, RoutedEventArgs const&)
{
+ auto lifetime = get_strong();
+
rootPage.NotifyUser({}, NotifyType::StatusMessage);
if (currentState == ScenarioState::Streaming)
{
diff --git a/Samples/Clipboard/cppwinrt/HistoryAndRoaming.cpp b/Samples/Clipboard/cppwinrt/HistoryAndRoaming.cpp
index 7a30ad193d..d4e2458f9b 100644
--- a/Samples/Clipboard/cppwinrt/HistoryAndRoaming.cpp
+++ b/Samples/Clipboard/cppwinrt/HistoryAndRoaming.cpp
@@ -46,6 +46,8 @@ namespace winrt::SDKTemplate::implementation
fire_and_forget HistoryAndRoaming::CopyButton_Click(IInspectable const&, RoutedEventArgs const&)
{
+ auto lifetime = get_strong();
+
// Generate a bitmap for our clipboard content.
RenderTargetBitmap target;
co_await target.RenderAsync(ClipboardContent());
diff --git a/Samples/DeviceEnumerationAndPairing/cppwinrt/Scenario3_BackgroundDeviceWatcher.cpp b/Samples/DeviceEnumerationAndPairing/cppwinrt/Scenario3_BackgroundDeviceWatcher.cpp
index 0a211322cf..1b9f25c378 100644
--- a/Samples/DeviceEnumerationAndPairing/cppwinrt/Scenario3_BackgroundDeviceWatcher.cpp
+++ b/Samples/DeviceEnumerationAndPairing/cppwinrt/Scenario3_BackgroundDeviceWatcher.cpp
@@ -140,6 +140,8 @@ namespace winrt::SDKTemplate::implementation
fire_and_forget Scenario3_BackgroundDeviceWatcher::OnTaskCompleted(BackgroundTaskRegistration const&, BackgroundTaskCompletedEventArgs const&)
{
+ auto lifetime = get_strong();
+
co_await resume_foreground(Dispatcher());
rootPage.NotifyUser(L"Background task completed", NotifyType::StatusMessage);
diff --git a/Samples/DisablingScreenCapture/README.md b/Samples/DisablingScreenCapture/README.md
index 8aa061ad0a..929ede4929 100644
--- a/Samples/DisablingScreenCapture/README.md
+++ b/Samples/DisablingScreenCapture/README.md
@@ -3,7 +3,7 @@ page_type: sample
languages:
- csharp
- cpp
-- cppcx
+- cppwinrt
products:
- windows
- windows-uwp
@@ -27,7 +27,10 @@ Shows how to disable screen capture by setting the
[IsScreenCaptureEnabled](http://msdn.microsoft.com/library/windows/apps/dn281123)
property of the
[ApplicationView](http://msdn.microsoft.com/library/windows/apps/hh701658)
-object.
+object,
+and by using methods of the
+[AppCapture](https://docs.microsoft.com/uwp/api/Windows.Media.Capture.AppCapture)
+class.
> **Note:** This sample is part of a large collection of UWP feature samples.
> You can download this sample as a standalone ZIP file
@@ -44,6 +47,7 @@ The sample consists of the following scenarios:
- Blocking screen capture for a specific page
by setting [IsScreenCaptureEnabled](http://msdn.microsoft.com/library/windows/apps/dn281123)
to **false** when the user navigates to the page, then setting it back to **true** when the user navigates away.
+- Allowing and blocking system-initiated app capture such as Xbox Game Bar.
**Note** The Windows universal samples require Visual Studio to build and Windows 10 to execute.
@@ -56,10 +60,11 @@ To obtain information about Microsoft Visual Studio and the tools for developing
### Reference
[ApplicationView class](https://msdn.microsoft.com/library/windows/apps/windows.ui.viewmanagement.applicationview.aspx)
+[Capture game audio, video, screenshots, and metadata](https://docs.microsoft.com/windows/uwp/gaming/capture-game-audio-video-screenshots-and-metadata)
### Related samples
-* [DisablingScreenCapture sample](/archived/DisablingScreenCapture/) for JavaScript (archived)
+* [DisablingScreenCapture sample](/archived/DisablingScreenCapture/) for C++/CX and JavaScript (archived)
## System requirements
diff --git a/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.sln b/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.sln
new file mode 100644
index 0000000000..5eb1c61b92
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29920.165
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DisablingScreenCapture", "DisablingScreenCapture.vcxproj", "{652E9CC9-5245-4EE1-B7F0-14C8523C7410}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|ARM.ActiveCfg = Debug|ARM
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|ARM.Build.0 = Debug|ARM
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|ARM.Deploy.0 = Debug|ARM
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|x64.ActiveCfg = Debug|x64
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|x64.Build.0 = Debug|x64
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|x64.Deploy.0 = Debug|x64
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|x86.ActiveCfg = Debug|Win32
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|x86.Build.0 = Debug|Win32
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Debug|x86.Deploy.0 = Debug|Win32
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|ARM.ActiveCfg = Release|ARM
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|ARM.Build.0 = Release|ARM
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|ARM.Deploy.0 = Release|ARM
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|x64.ActiveCfg = Release|x64
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|x64.Build.0 = Release|x64
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|x64.Deploy.0 = Release|x64
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|x86.ActiveCfg = Release|Win32
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|x86.Build.0 = Release|Win32
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F057752F-09D6-40E9-9FAC-E2922523F117}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.vcxproj b/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.vcxproj
new file mode 100644
index 0000000000..9a520dee2f
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.vcxproj
@@ -0,0 +1,200 @@
+
+
+
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), LICENSE))\SharedContent
+
+
+ true
+ {652E9CC9-5245-4EE1-B7F0-14C8523C7410}
+ DisablingScreenCapture
+ SDKTemplate
+ en-US
+ 15.0
+ true
+ Windows Store
+ 10.0
+ 10.0.18362.0
+ $(WindowsTargetPlatformVersion)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);$(SharedContentDir)\cppwinrt
+ true
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ 4453;28204
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+ Scenario1_Enable.xaml
+
+
+ Scenario2_Disable.xaml
+
+
+ Scenario3_AppCapture.xaml
+
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+ SampleConfiguration.h
+
+
+ Scenario1_Enable.xaml
+
+
+ Scenario2_Disable.xaml
+
+
+ Scenario3_AppCapture.xaml
+
+
+ Create
+ pch.h
+
+
+ Project.idl
+
+
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+ Assets\ladybug.wmv
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.vcxproj.filters b/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.vcxproj.filters
new file mode 100644
index 0000000000..ff7d01c068
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/DisablingScreenCapture.vcxproj.filters
@@ -0,0 +1,65 @@
+
+
+
+
+ 4416d50a-7676-4d0a-9b2c-91ff70c6047f
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+
\ No newline at end of file
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Package.appxmanifest b/Samples/DisablingScreenCapture/cppwinrt/Package.appxmanifest
new file mode 100644
index 0000000000..0044567584
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Package.appxmanifest
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Disabling Screen Capture C++/WinRT Sample
+ Microsoft Corporation
+ Assets\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Project.idl b/Samples/DisablingScreenCapture/cppwinrt/Project.idl
new file mode 100644
index 0000000000..bd10fc1e01
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Project.idl
@@ -0,0 +1,31 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+namespace SDKTemplate
+{
+ [default_interface]
+ runtimeclass Scenario1_Enable : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario1_Enable();
+ }
+
+ [default_interface]
+ runtimeclass Scenario2_Disable : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario2_Disable();
+ }
+
+ [default_interface]
+ runtimeclass Scenario3_AppCapture : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario3_AppCapture();
+ }
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/SampleConfiguration.cpp b/Samples/DisablingScreenCapture/cppwinrt/SampleConfiguration.cpp
new file mode 100644
index 0000000000..2a7faeaddd
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/SampleConfiguration.cpp
@@ -0,0 +1,31 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include
+#include "MainPage.h"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::SDKTemplate;
+
+hstring implementation::MainPage::FEATURE_NAME()
+{
+ return L"Disabling screen capture C++/WinRT sample";
+}
+
+IVector implementation::MainPage::scenariosInner = winrt::single_threaded_observable_vector(
+{
+ Scenario{ L"Enabling screen capture", xaml_typename() },
+ Scenario{ L"Disabling screen capture", xaml_typename() },
+ Scenario{ L"Managing AppCapture", xaml_typename() },
+});
diff --git a/Samples/DisablingScreenCapture/cppwinrt/SampleConfiguration.h b/Samples/DisablingScreenCapture/cppwinrt/SampleConfiguration.h
new file mode 100644
index 0000000000..ba0eb7c8c2
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/SampleConfiguration.h
@@ -0,0 +1,17 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace winrt::SDKTemplate
+{
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.cpp b/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.cpp
new file mode 100644
index 0000000000..1245dd79b9
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.cpp
@@ -0,0 +1,22 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario1_Enable.h"
+#include "Scenario1_Enable.g.cpp"
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario1_Enable::Scenario1_Enable()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.h b/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.h
new file mode 100644
index 0000000000..05b24c3a96
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.h
@@ -0,0 +1,29 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario1_Enable.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario1_Enable : Scenario1_EnableT
+ {
+ Scenario1_Enable();
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario1_Enable : Scenario1_EnableT
+ {
+ };
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.xaml b/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.xaml
new file mode 100644
index 0000000000..e8bfd236c9
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario1_Enable.xaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ Screen capture allowed
+
+
+ By default, screen capture is allowed.
+
+
+
+
+
+
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.cpp b/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.cpp
new file mode 100644
index 0000000000..8a556d6766
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.cpp
@@ -0,0 +1,39 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario2_Disable.h"
+#include "Scenario2_Disable.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario2_Disable::Scenario2_Disable()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario2_Disable::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ // Disable screen capture when the user navigates to this page.
+ Windows::UI::ViewManagement::ApplicationView::GetForCurrentView().IsScreenCaptureEnabled(false);
+ }
+
+ void Scenario2_Disable::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ // Re-enable screen capture when the user navigates away from this page.
+ Windows::UI::ViewManagement::ApplicationView::GetForCurrentView().IsScreenCaptureEnabled(true);
+ }
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.h b/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.h
new file mode 100644
index 0000000000..ec8121b89b
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.h
@@ -0,0 +1,31 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario2_Disable.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario2_Disable : Scenario2_DisableT
+ {
+ Scenario2_Disable();
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario2_Disable : Scenario2_DisableT
+ {
+ };
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.xaml b/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.xaml
new file mode 100644
index 0000000000..e31651e53c
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario2_Disable.xaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ Screen capture disabled
+
+
+ This view will be excluded from screen captures.
+
+
+
+
+
+
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.cpp b/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.cpp
new file mode 100644
index 0000000000..a82d97e69e
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.cpp
@@ -0,0 +1,63 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario3_AppCapture.h"
+#include "Scenario3_AppCapture.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Media::Capture;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario3_AppCapture::Scenario3_AppCapture()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario3_AppCapture::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ appCapture = AppCapture::GetForCurrentView();
+ capturingChangedToken = appCapture.CapturingChanged({ get_weak(), &Scenario3_AppCapture::AppCapture_CapturingChanged });
+ UpdateCaptureStatus();
+ }
+
+ void Scenario3_AppCapture::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ appCapture.CapturingChanged(capturingChangedToken);
+
+ // Re-enable app capture when navigating away.
+ AppCapture::SetAllowedAsync(true);
+ }
+
+ fire_and_forget Scenario3_AppCapture::AllowAppCaptureCheckBox_Toggled(IInspectable const& sender, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+ ToggleSwitch toggleSwitch = sender.as();
+ co_await AppCapture::SetAllowedAsync(toggleSwitch.IsOn());
+ }
+
+ void Scenario3_AppCapture::AppCapture_CapturingChanged(AppCapture const&, IInspectable const&)
+ {
+ UpdateCaptureStatus();
+ }
+
+ void Scenario3_AppCapture::UpdateCaptureStatus()
+ {
+ hstring audioStatus = appCapture.IsCapturingAudio() ? L"Audio is being captured." : L"Audio is not being captured.";
+ hstring videoStatus = appCapture.IsCapturingVideo() ? L"Video is being captured." : L"Video is not being captured.";
+ rootPage.NotifyUser(audioStatus + L"\n" + videoStatus, NotifyType::StatusMessage);
+ }
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.h b/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.h
new file mode 100644
index 0000000000..ee445ccf35
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.h
@@ -0,0 +1,41 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario3_AppCapture.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario3_AppCapture : Scenario3_AppCaptureT
+ {
+ Scenario3_AppCapture();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget AllowAppCaptureCheckBox_Toggled(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::RoutedEventArgs const&);
+ void AppCapture_CapturingChanged(Windows::Media::Capture::AppCapture const&, Windows::Foundation::IInspectable const&);
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Media::Capture::AppCapture appCapture{ nullptr };
+ event_token capturingChangedToken{};
+
+ void UpdateCaptureStatus();
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario3_AppCapture : Scenario3_AppCaptureT
+ {
+ };
+}
diff --git a/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.xaml b/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.xaml
new file mode 100644
index 0000000000..e15a822ba3
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/Scenario3_AppCapture.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+ Managing AppCapture
+
+
+ Disabling screen capture prevents the view's video from being captured
+ by system-intiiated app capture such as the Xbox Game Bar.
+ You can also customize app capture behavior directly.
+
+
+
+
+
+
+
+
diff --git a/Samples/DisablingScreenCapture/cppwinrt/packages.config b/Samples/DisablingScreenCapture/cppwinrt/packages.config
new file mode 100644
index 0000000000..68fd1b237d
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Samples/DisablingScreenCapture/cppwinrt/pch.cpp b/Samples/DisablingScreenCapture/cppwinrt/pch.cpp
new file mode 100644
index 0000000000..01484ff5aa
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/pch.cpp
@@ -0,0 +1,6 @@
+//
+// pch.cpp
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/DisablingScreenCapture/cppwinrt/pch.h b/Samples/DisablingScreenCapture/cppwinrt/pch.h
new file mode 100644
index 0000000000..d4487143c2
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cppwinrt/pch.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include
+#include "winrt/Windows.Foundation.h"
+#include "winrt/Windows.Foundation.Collections.h"
+#include "winrt/Windows.ApplicationModel.Activation.h"
+#include "winrt/Windows.Media.Capture.h"
+#include "winrt/Windows.System.h"
+#include "winrt/Windows.UI.Core.h"
+#include "winrt/Windows.UI.ViewManagement.h"
+#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.UI.Xaml.Automation.Peers.h"
+#include "winrt/Windows.UI.Xaml.Controls.h"
+#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
+#include "winrt/Windows.UI.Xaml.Documents.h"
+#include "winrt/Windows.UI.Xaml.Interop.h"
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.Xaml.Media.h"
+#include "winrt/Windows.UI.Xaml.Navigation.h"
diff --git a/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.csproj b/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.csproj
index fde6d5654e..ab8f803e68 100644
--- a/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.csproj
+++ b/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.csproj
@@ -108,6 +108,9 @@
Scenario2_Disable.xaml
+
+ Scenario3_AppCapture.xaml
+
@@ -135,6 +138,11 @@
MSBuild:Compile
Designer
+
+ Scenario3_AppCapture.xaml
+ MSBuild:Compile
+ Designer
+
Styles\Styles.xaml
MSBuild:Compile
@@ -166,6 +174,9 @@
Assets\windows-sdk.png
+
+ Assets\ladybug.wmv
+
diff --git a/Samples/DisablingScreenCapture/cs/Package.appxmanifest b/Samples/DisablingScreenCapture/cs/Package.appxmanifest
index ecc9a3d548..1fb13c4eb4 100644
--- a/Samples/DisablingScreenCapture/cs/Package.appxmanifest
+++ b/Samples/DisablingScreenCapture/cs/Package.appxmanifest
@@ -21,7 +21,7 @@
-
+
diff --git a/Samples/DisablingScreenCapture/cs/SampleConfiguration.cs b/Samples/DisablingScreenCapture/cs/SampleConfiguration.cs
index 57577d85f0..f025fc0c3f 100644
--- a/Samples/DisablingScreenCapture/cs/SampleConfiguration.cs
+++ b/Samples/DisablingScreenCapture/cs/SampleConfiguration.cs
@@ -23,6 +23,7 @@ public partial class MainPage : Page
{
new Scenario() { Title="Enabling screen capture", ClassType=typeof(Scenario1_Enable) },
new Scenario() { Title="Disabling screen capture", ClassType=typeof(Scenario2_Disable) },
+ new Scenario() { Title="Managing AppCapture", ClassType=typeof(Scenario3_AppCapture) },
};
}
diff --git a/Samples/DisablingScreenCapture/cs/Scenario3_AppCapture.xaml.cs b/Samples/DisablingScreenCapture/cs/Scenario3_AppCapture.xaml.cs
new file mode 100644
index 0000000000..b214022ff3
--- /dev/null
+++ b/Samples/DisablingScreenCapture/cs/Scenario3_AppCapture.xaml.cs
@@ -0,0 +1,63 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.Media.Capture;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace SDKTemplate
+{
+ public sealed partial class Scenario3_AppCapture : Page
+ {
+ AppCapture appCapture;
+ MainPage rootPage = MainPage.Current;
+
+ public Scenario3_AppCapture()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ appCapture = AppCapture.GetForCurrentView();
+ appCapture.CapturingChanged += AppCapture_CapturingChanged;
+ UpdateCaptureStatus();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ appCapture.CapturingChanged -= AppCapture_CapturingChanged;
+
+ // Re-enable app capture when navigating away.
+ var task = AppCapture.SetAllowedAsync(true);
+ }
+
+ async void AllowAppCaptureCheckBox_Toggled(object sender, RoutedEventArgs e)
+ {
+ ToggleSwitch toggleSwitch = (ToggleSwitch)sender;
+ await AppCapture.SetAllowedAsync(toggleSwitch.IsOn);
+ }
+
+ void AppCapture_CapturingChanged(AppCapture sender, object e)
+ {
+ UpdateCaptureStatus();
+ }
+
+ void UpdateCaptureStatus()
+ {
+ string audioStatus = appCapture.IsCapturingAudio ? "Audio is being captured." : "Audio is not being captured.";
+ string videoStatus = appCapture.IsCapturingVideo ? "Video is being captured." : "Video is not being captured.";
+ rootPage.NotifyUser(audioStatus + "\n" + videoStatus, NotifyType.StatusMessage);
+ }
+ }
+}
diff --git a/Samples/DisablingScreenCapture/shared/Scenario1_Enable.xaml b/Samples/DisablingScreenCapture/shared/Scenario1_Enable.xaml
index dc573cc747..e8bfd236c9 100644
--- a/Samples/DisablingScreenCapture/shared/Scenario1_Enable.xaml
+++ b/Samples/DisablingScreenCapture/shared/Scenario1_Enable.xaml
@@ -28,6 +28,9 @@
By default, screen capture is allowed.
+
diff --git a/Samples/DisablingScreenCapture/shared/Scenario2_Disable.xaml b/Samples/DisablingScreenCapture/shared/Scenario2_Disable.xaml
index 9fe8e6947e..e31651e53c 100644
--- a/Samples/DisablingScreenCapture/shared/Scenario2_Disable.xaml
+++ b/Samples/DisablingScreenCapture/shared/Scenario2_Disable.xaml
@@ -28,6 +28,9 @@
This view will be excluded from screen captures.
+
diff --git a/Samples/DisablingScreenCapture/shared/Scenario3_AppCapture.xaml b/Samples/DisablingScreenCapture/shared/Scenario3_AppCapture.xaml
new file mode 100644
index 0000000000..e15a822ba3
--- /dev/null
+++ b/Samples/DisablingScreenCapture/shared/Scenario3_AppCapture.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+ Managing AppCapture
+
+
+ Disabling screen capture prevents the view's video from being captured
+ by system-intiiated app capture such as the Xbox Game Bar.
+ You can also customize app capture behavior directly.
+
+
+
+
+
+
+
+
diff --git a/Samples/DisplayOrientation/README.md b/Samples/DisplayOrientation/README.md
index befdcdd53f..3e0e22b816 100644
--- a/Samples/DisplayOrientation/README.md
+++ b/Samples/DisplayOrientation/README.md
@@ -4,6 +4,7 @@ languages:
- csharp
- cpp
- cppcx
+- cppwinrt
products:
- windows
- windows-uwp
diff --git a/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.cpp b/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.cpp
index 53bfd385b0..b490bf9809 100644
--- a/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.cpp
+++ b/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.cpp
@@ -79,7 +79,7 @@ void Scenario1_Orientation::UpdateContent()
AutoRotationPreferencesTextBlock->Text = OrientationsToString(DisplayInformation::AutoRotationPreferences);
}
-void Scenario1_Orientation::ApplyRotationLock()
+void Scenario1_Orientation::ApplyRotationLock_Click(Object^ sender, RoutedEventArgs^ e)
{
DisplayOrientations orientations = DisplayOrientations::None;
diff --git a/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.h b/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.h
index b46d395802..9bf02d84bd 100644
--- a/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.h
+++ b/Samples/DisplayOrientation/cpp/Scenario1_Orientation.xaml.h
@@ -21,7 +21,6 @@ namespace SDKTemplate
{
public:
Scenario1_Orientation();
- void ApplyRotationLock();
protected:
void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
@@ -33,6 +32,7 @@ namespace SDKTemplate
void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ e);
static Platform::String^ OrientationsToString(Windows::Graphics::Display::DisplayOrientations orientations);
void UpdateContent();
+ void ApplyRotationLock_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
Windows::Foundation::EventRegistrationToken orientationChangedToken;
};
diff --git a/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.sln b/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.sln
new file mode 100644
index 0000000000..1ac799a502
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29920.165
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DisplayOrientation", "DisplayOrientation.vcxproj", "{4D15177F-65F2-5C7B-9D64-93468149E30B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|ARM.ActiveCfg = Debug|ARM
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|ARM.Build.0 = Debug|ARM
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|ARM.Deploy.0 = Debug|ARM
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|x64.ActiveCfg = Debug|x64
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|x64.Build.0 = Debug|x64
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|x64.Deploy.0 = Debug|x64
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|x86.ActiveCfg = Debug|Win32
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|x86.Build.0 = Debug|Win32
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Debug|x86.Deploy.0 = Debug|Win32
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|ARM.ActiveCfg = Release|ARM
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|ARM.Build.0 = Release|ARM
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|ARM.Deploy.0 = Release|ARM
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|x64.ActiveCfg = Release|x64
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|x64.Build.0 = Release|x64
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|x64.Deploy.0 = Release|x64
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|x86.ActiveCfg = Release|Win32
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|x86.Build.0 = Release|Win32
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {5E71175D-B582-4482-AD9C-A3A6B6C2A079}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.vcxproj b/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.vcxproj
new file mode 100644
index 0000000000..c2f80fa08c
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.vcxproj
@@ -0,0 +1,181 @@
+
+
+
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), LICENSE))\SharedContent
+
+
+ true
+ {4D15177F-65F2-5C7B-9D64-93468149E30B}
+ DisplayOrientation
+ SDKTemplate
+ en-US
+ 15.0
+ true
+ Windows Store
+ 10.0
+ 10.0.18362.0
+ $(WindowsTargetPlatformVersion)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);$(SharedContentDir)\cppwinrt
+ true
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ 4453;28204
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+ ..\shared\Scenario1_Orientation.xaml
+
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+ SampleConfiguration.h
+
+
+ ..\shared\Scenario1_Orientation.xaml
+
+
+ Create
+ pch.h
+
+
+ Project.idl
+
+
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.vcxproj.filters b/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.vcxproj.filters
new file mode 100644
index 0000000000..89d810881f
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/DisplayOrientation.vcxproj.filters
@@ -0,0 +1,62 @@
+
+
+
+
+ 4416d50a-7676-4d0a-9b2c-91ff70c6047f
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/DisplayOrientation/cppwinrt/Package.appxmanifest b/Samples/DisplayOrientation/cppwinrt/Package.appxmanifest
new file mode 100644
index 0000000000..c491c8bccd
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/Package.appxmanifest
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Display Orientation C++/WinRT Sample
+ Microsoft Corporation
+ Assets\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/DisplayOrientation/cppwinrt/Project.idl b/Samples/DisplayOrientation/cppwinrt/Project.idl
new file mode 100644
index 0000000000..70a1f53f2b
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/Project.idl
@@ -0,0 +1,19 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+namespace SDKTemplate
+{
+ [default_interface]
+ runtimeclass Scenario1_Orientation : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario1_Orientation();
+ }
+}
diff --git a/Samples/DisplayOrientation/cppwinrt/SampleConfiguration.cpp b/Samples/DisplayOrientation/cppwinrt/SampleConfiguration.cpp
new file mode 100644
index 0000000000..3cfdd31a4b
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/SampleConfiguration.cpp
@@ -0,0 +1,29 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include
+#include "MainPage.h"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::SDKTemplate;
+
+hstring implementation::MainPage::FEATURE_NAME()
+{
+ return L"Display Orientation C++/WinRT Sample";
+}
+
+IVector implementation::MainPage::scenariosInner = winrt::single_threaded_observable_vector(
+{
+ Scenario{ L"Show and lock orientation", xaml_typename() },
+});
diff --git a/Samples/DisplayOrientation/cppwinrt/SampleConfiguration.h b/Samples/DisplayOrientation/cppwinrt/SampleConfiguration.h
new file mode 100644
index 0000000000..ba0eb7c8c2
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/SampleConfiguration.h
@@ -0,0 +1,17 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace winrt::SDKTemplate
+{
+}
diff --git a/Samples/DisplayOrientation/cppwinrt/Scenario1_Orientation.cpp b/Samples/DisplayOrientation/cppwinrt/Scenario1_Orientation.cpp
new file mode 100644
index 0000000000..fdb6e5d353
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/Scenario1_Orientation.cpp
@@ -0,0 +1,102 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario1_Orientation.h"
+#include "Scenario1_Orientation.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Graphics::Display;
+using namespace winrt::Windows::UI::Xaml;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario1_Orientation::Scenario1_Orientation()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario1_Orientation::OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const&)
+ {
+ displayInfo = DisplayInformation::GetForCurrentView();
+ orientationChangedToken = displayInfo.OrientationChanged({ get_weak(), &Scenario1_Orientation::OnOrientationChanged });
+ UpdateContent();
+ }
+
+ void Scenario1_Orientation::OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const&)
+ {
+ displayInfo.OrientationChanged(orientationChangedToken);
+ }
+
+ void Scenario1_Orientation::OnOrientationChanged(DisplayInformation const&, IInspectable const&)
+ {
+ UpdateContent();
+ }
+
+ hstring Scenario1_Orientation::OrientationsToString(DisplayOrientations orientations)
+ {
+ std::wstring result = L"None";
+
+ if ((orientations & DisplayOrientations::Landscape) == DisplayOrientations::Landscape)
+ {
+ result += L", Landscape";
+ }
+ if ((orientations & DisplayOrientations::Portrait) == DisplayOrientations::Portrait)
+ {
+ result += L", Portrait";
+ }
+ if ((orientations & DisplayOrientations::LandscapeFlipped) == DisplayOrientations::LandscapeFlipped)
+ {
+ result += L", LandscapeFlipped";
+ }
+ if ((orientations & DisplayOrientations::PortraitFlipped) == DisplayOrientations::PortraitFlipped)
+ {
+ result += L", PortraitFlipped";
+ }
+ if (result != L"None")
+ {
+ result = result.substr(6);
+ }
+ return hstring{ result };
+ }
+
+ void Scenario1_Orientation::UpdateContent()
+ {
+ NativeOrientationTextBlock().Text(OrientationsToString(displayInfo.NativeOrientation()));
+ CurrentOrientationTextBlock().Text(OrientationsToString(displayInfo.CurrentOrientation()));
+ AutoRotationPreferencesTextBlock().Text(OrientationsToString(DisplayInformation::AutoRotationPreferences()));
+ }
+
+ void Scenario1_Orientation::ApplyRotationLock_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ DisplayOrientations orientations = DisplayOrientations::None;
+
+ if (PreferLandscape().IsChecked().Value())
+ {
+ orientations = orientations | DisplayOrientations::Landscape;
+ }
+ if (PreferPortrait().IsChecked().Value())
+ {
+ orientations = orientations | DisplayOrientations::Portrait;
+ }
+ if (PreferLandscapeFlipped().IsChecked().Value())
+ {
+ orientations = orientations | DisplayOrientations::LandscapeFlipped;
+ }
+ if (PreferPortraitFlipped().IsChecked().Value())
+ {
+ orientations = orientations | DisplayOrientations::PortraitFlipped;
+ }
+ DisplayInformation::AutoRotationPreferences(orientations);
+ UpdateContent();
+ }
+}
diff --git a/Samples/DisplayOrientation/cppwinrt/Scenario1_Orientation.h b/Samples/DisplayOrientation/cppwinrt/Scenario1_Orientation.h
new file mode 100644
index 0000000000..fa7a246499
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/Scenario1_Orientation.h
@@ -0,0 +1,42 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario1_Orientation.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario1_Orientation : Scenario1_OrientationT
+ {
+ Scenario1_Orientation();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ void ApplyRotationLock_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ Windows::Graphics::Display::DisplayInformation displayInfo{ nullptr };
+ event_token orientationChangedToken{};
+
+ void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation const&, Windows::Foundation::IInspectable const&);
+ hstring OrientationsToString(Windows::Graphics::Display::DisplayOrientations orientations);
+ void UpdateContent();
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario1_Orientation : Scenario1_OrientationT
+ {
+ };
+}
diff --git a/Samples/DisplayOrientation/cppwinrt/packages.config b/Samples/DisplayOrientation/cppwinrt/packages.config
new file mode 100644
index 0000000000..68fd1b237d
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Samples/DisplayOrientation/cppwinrt/pch.cpp b/Samples/DisplayOrientation/cppwinrt/pch.cpp
new file mode 100644
index 0000000000..01484ff5aa
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/pch.cpp
@@ -0,0 +1,6 @@
+//
+// pch.cpp
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/DisplayOrientation/cppwinrt/pch.h b/Samples/DisplayOrientation/cppwinrt/pch.h
new file mode 100644
index 0000000000..fc331739ad
--- /dev/null
+++ b/Samples/DisplayOrientation/cppwinrt/pch.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include
+#include "winrt/Windows.Foundation.h"
+#include "winrt/Windows.Foundation.Collections.h"
+#include "winrt/Windows.ApplicationModel.Activation.h"
+#include "winrt/Windows.Graphics.Display.h"
+#include "winrt/Windows.System.h"
+#include "winrt/Windows.UI.Core.h"
+#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.UI.Xaml.Automation.Peers.h"
+#include "winrt/Windows.UI.Xaml.Controls.h"
+#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
+#include "winrt/Windows.UI.Xaml.Documents.h"
+#include "winrt/Windows.UI.Xaml.Interop.h"
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.Xaml.Media.h"
+#include "winrt/Windows.UI.Xaml.Navigation.h"
diff --git a/Samples/DisplayOrientation/cs/Scenario1_Orientation.xaml.cs b/Samples/DisplayOrientation/cs/Scenario1_Orientation.xaml.cs
index 8c441f2f48..3fa8ae7ee7 100644
--- a/Samples/DisplayOrientation/cs/Scenario1_Orientation.xaml.cs
+++ b/Samples/DisplayOrientation/cs/Scenario1_Orientation.xaml.cs
@@ -52,7 +52,7 @@ private void UpdateContent()
AutoRotationPreferencesTextBlock.Text = DisplayInformation.AutoRotationPreferences.ToString();
}
- private void ApplyRotationLock()
+ private void ApplyRotationLock_Click(object sender, RoutedEventArgs e)
{
DisplayOrientations orientations = DisplayOrientations.None;
if (PreferLandscape.IsChecked.Value)
diff --git a/Samples/DisplayOrientation/shared/Scenario1_Orientation.xaml b/Samples/DisplayOrientation/shared/Scenario1_Orientation.xaml
index 1b33117298..27df619cfd 100644
--- a/Samples/DisplayOrientation/shared/Scenario1_Orientation.xaml
+++ b/Samples/DisplayOrientation/shared/Scenario1_Orientation.xaml
@@ -23,6 +23,8 @@
Reports the native display orientation, current display orientation,
and sets auto-rotation preferences.
+ Note that the operating system is not obligated to honor auto-rotation preferences.
+ In particular, the preferences are not respected in overlapped windowing mode.
@@ -41,7 +43,7 @@
-
+
diff --git a/Samples/HolographicMixedRealityCapture/cpp/MediaCaptureManager.cpp b/Samples/HolographicMixedRealityCapture/cpp/MediaCaptureManager.cpp
index 7ffe4aca38..af0cb4ab84 100644
--- a/Samples/HolographicMixedRealityCapture/cpp/MediaCaptureManager.cpp
+++ b/Samples/HolographicMixedRealityCapture/cpp/MediaCaptureManager.cpp
@@ -5,6 +5,7 @@
#include
using namespace HolographicMRCSample;
+using namespace Windows::Devices::Enumeration;
using namespace Windows::Media;
using namespace Windows::Media::Capture;
@@ -32,33 +33,50 @@ Concurrency::task MediaCaptureManager::InitializeAsync(IMFDXGIDeviceManage
OutputDebugString(args->Message->Data());
});
- auto initSetting = ref new Windows::Media::Capture::MediaCaptureInitializationSettings;
- initSetting->StreamingCaptureMode = Windows::Media::Capture::StreamingCaptureMode::AudioAndVideo;
- initSetting->MediaCategory = Windows::Media::Capture::MediaCategory::Media;
-
if (pDxgiDeviceManager)
{
- // Optionally, you can put your D3D device into MediaCapture.
- // But, in most case, this is not mandatory.
m_spMFDXGIDeviceManager = pDxgiDeviceManager;
- Microsoft::WRL::ComPtr spAdvancedSettings;
- ((IUnknown*)initSetting)->QueryInterface(IID_PPV_ARGS(&spAdvancedSettings));
- spAdvancedSettings->SetDirectxDeviceManager(m_spMFDXGIDeviceManager.Get());
}
- return Concurrency::create_task(m_mediaCapture->InitializeAsync(initSetting)).then([this]()
+ return Concurrency::create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture)).then([this](DeviceInformationCollection^ devices)
{
- auto lock = m_lock.LockExclusive();
+ auto initSetting = ref new Windows::Media::Capture::MediaCaptureInitializationSettings;
+ initSetting->StreamingCaptureMode = Windows::Media::Capture::StreamingCaptureMode::AudioAndVideo;
+ initSetting->MediaCategory = Windows::Media::Capture::MediaCategory::Media;
- if (m_mediaCapture->MediaCaptureSettings->AudioDeviceId && m_mediaCapture->MediaCaptureSettings->VideoDeviceId)
+ // Select video conferencing profile since it provides better performance on HoloLens 2
+ for (auto cameraDeviceInfo : devices)
{
- // MediaCapture is initialized with valid audio and video device.
- m_currentState = Initialized;
+ auto profiles = m_mediaCapture->FindKnownVideoProfiles(cameraDeviceInfo->Id, KnownVideoProfile::VideoConferencing);
+ if (profiles->Size > 0)
+ {
+ initSetting->VideoProfile = profiles->GetAt(0);
+ }
}
- else
+
+ if (m_spMFDXGIDeviceManager)
{
- OutputDebugString(L"MediaCapture is initialized without valid sources.\n");
+ // Optionally, you can put your D3D device into MediaCapture.
+ // But, in most case, this is not mandatory.
+ Microsoft::WRL::ComPtr spAdvancedSettings;
+ ((IUnknown*)initSetting)->QueryInterface(IID_PPV_ARGS(&spAdvancedSettings));
+ spAdvancedSettings->SetDirectxDeviceManager(m_spMFDXGIDeviceManager.Get());
}
+
+ return Concurrency::create_task(m_mediaCapture->InitializeAsync(initSetting)).then([this]()
+ {
+ auto lock = m_lock.LockExclusive();
+
+ if (m_mediaCapture->MediaCaptureSettings->AudioDeviceId && m_mediaCapture->MediaCaptureSettings->VideoDeviceId)
+ {
+ // MediaCapture is initialized with valid audio and video device.
+ m_currentState = Initialized;
+ }
+ else
+ {
+ OutputDebugString(L"MediaCapture is initialized without valid sources.\n");
+ }
+ });
});
}
diff --git a/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcAudioEffectDefinition.h b/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcAudioEffectDefinition.h
index 6e6618eb10..64daa49131 100644
--- a/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcAudioEffectDefinition.h
+++ b/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcAudioEffectDefinition.h
@@ -15,6 +15,20 @@
//
#define PROPERTY_MIXERMODE L"MixerMode"
+//
+// LoopbackGain: Gain to apply to system audio volume.
+// Type : double (0.0 to 5.0)
+// Default: 1.0
+//
+#define PROPERTY_LOOPBACKGAIN L"LoopbackGain"
+
+//
+// MicrophoneGain: Gain to apply to mic volume.
+// Type : double (0.0 to 5.0)
+// Default: 1.0
+//
+#define PROPERTY_MICROPHONEGAIN L"MicrophoneGain"
+
namespace MrcEffectDefinitions
{
public enum class AudioMixerMode
@@ -64,8 +78,36 @@ namespace MrcEffectDefinitions
}
}
+ property double LoopbackGain
+ {
+ double get()
+ {
+ return GetValueFromPropertySet(m_propertySet, PROPERTY_LOOPBACKGAIN, DefaultLoopBackGain);
+ }
+
+ void set(double newValue)
+ {
+ m_propertySet->Insert(PROPERTY_LOOPBACKGAIN, static_cast(newValue));
+ }
+ }
+
+ property double MicrophoneGain
+ {
+ double get()
+ {
+ return GetValueFromPropertySet(m_propertySet, PROPERTY_MICROPHONEGAIN, DefaultMicrophoneGain);
+ }
+
+ void set(double newValue)
+ {
+ m_propertySet->Insert(PROPERTY_MICROPHONEGAIN, static_cast(newValue));
+ }
+ }
+
private:
static constexpr AudioMixerMode DefaultAudioMixerMode = AudioMixerMode::MicAndLoopback;
+ static constexpr double DefaultLoopBackGain = 1.0f;
+ static constexpr double DefaultMicrophoneGain = 1.0f;
private:
Platform::String^ m_activatableClassId = ref new Platform::String(RUNTIMECLASS_MIXEDREALITYCAPTURE_AUDIO_EFFECT);
Windows::Foundation::Collections::PropertySet^ m_propertySet = ref new Windows::Foundation::Collections::PropertySet();
diff --git a/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.cpp b/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.cpp
index 346c6e4c25..4ab392785c 100644
--- a/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.cpp
+++ b/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.cpp
@@ -11,4 +11,8 @@ MrcVideoEffectDefinition::MrcVideoEffectDefinition()
VideoStabilizationEnabled = DefaultVideoStabilizationEnabled;
VideoStabilizationBufferLength = DefaultVideoStabilizationBufferLength;
GlobalOpacityCoefficient = DefaultGlobalOpacityCoefficient;
+ BlankOnProtectedContent = DefaultBlankOnProtectedContent;
+ ShowHiddenMesh = DefaultShowHiddenMesh;
+ OutputSize = DefaultOutputSize;
+ PreferredHologramPerspective = DefaultPreferredHologramPerspective;
}
diff --git a/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.h b/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.h
index 488d0154b7..e916034a64 100644
--- a/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.h
+++ b/Samples/HolographicMixedRealityCapture/cpp/MrcEffectDefinitions/MrcVideoEffectDefinition.h
@@ -49,6 +49,38 @@
//
#define PROPERTY_GLOBALOPACITYCOEFFICIENT L"GlobalOpacityCoefficient"
+//
+// BlankOnProtectedContent: Flag to enable or disable returning an empty frame if there is a 2d UWP app showing protected content.
+// If this flag is false and a 2d UWP app is showing protected content, the 2d UWP app will be replaced by
+// a protected content texture in the mixed reality capture.
+// Type : bool
+// Default: false
+//
+#define PROPERTY_BLANKONPROTECTEDCONTENT L"BlankOnProtectedContent"
+
+//
+// ShowHiddenMesh: Flag to enable or disable showing the holographic camera's hidden area mesh and neighboring content.
+// Type : bool
+// Default: false
+//
+#define PROPERTY_SHOWHIDDENMESH L"ShowHiddenMesh"
+
+//
+// OutputSize: Set the desired output size after cropping for video stabilization. A default crop size is chosen if 0 or an invalid output size is specified.
+// Type : Windows.Foundation.Size
+// Default: (0,0)
+//
+#define PROPERTY_OUTPUTSIZE L"OutputSize"
+
+//
+// PreferredHologramPerspective: Enum used to indicate which holographic camera view configuration should be captured
+// Type: MixedRealityCapturePerspective as UINT32
+// 0: App won't be asked to render from the photo/video camera
+// 1: App is rendered from the photo/video camera
+// Default: 1
+//
+#define PROPERTY_PREFERREDHOLOGRAMPERSPECTIVE L"PreferredHologramPerspective"
+
//
// Maximum value of VideoStabilizationBufferLength
// This number is defined and used in MixedRealityCaptureVideoEffect
@@ -57,6 +89,12 @@
namespace MrcEffectDefinitions
{
+ public enum class MixedRealityCapturePerspective
+ {
+ Display = 0,
+ PhotoVideoCamera = 1,
+ };
+
public ref class MrcVideoEffectDefinition sealed : public Windows::Media::Effects::IVideoEffectDefinition
{
public:
@@ -162,7 +200,6 @@ namespace MrcEffectDefinitions
}
}
-
property uint32_t VideoStabilizationMaximumBufferLength
{
uint32_t get()
@@ -171,6 +208,58 @@ namespace MrcEffectDefinitions
}
}
+ property bool BlankOnProtectedContent
+ {
+ bool get()
+ {
+ return GetValueFromPropertySet(m_propertySet, PROPERTY_BLANKONPROTECTEDCONTENT, DefaultBlankOnProtectedContent);
+ }
+
+ void set(bool newValue)
+ {
+ m_propertySet->Insert(PROPERTY_BLANKONPROTECTEDCONTENT, newValue);
+ }
+ }
+
+ property bool ShowHiddenMesh
+ {
+ bool get()
+ {
+ return GetValueFromPropertySet(m_propertySet, PROPERTY_SHOWHIDDENMESH, DefaultShowHiddenMesh);
+ }
+
+ void set(bool newValue)
+ {
+ m_propertySet->Insert(PROPERTY_SHOWHIDDENMESH, newValue);
+ }
+ }
+
+ property Windows::Foundation::Size OutputSize
+ {
+ Windows::Foundation::Size get()
+ {
+ return GetValueFromPropertySet(m_propertySet, PROPERTY_OUTPUTSIZE, DefaultOutputSize);
+ }
+
+ void set(Windows::Foundation::Size newValue)
+ {
+ m_propertySet->Insert(PROPERTY_OUTPUTSIZE, static_cast(newValue));
+ }
+ }
+
+ property MixedRealityCapturePerspective PreferredHologramPerspective
+ {
+ MixedRealityCapturePerspective get()
+ {
+ return GetValueFromPropertySet(m_propertySet, PROPERTY_PREFERREDHOLOGRAMPERSPECTIVE, DefaultPreferredHologramPerspective);
+ }
+
+ void set(MixedRealityCapturePerspective newValue)
+ {
+ m_propertySet->Insert(PROPERTY_PREFERREDHOLOGRAMPERSPECTIVE, static_cast(newValue));
+ }
+ }
+
private:
static constexpr Windows::Media::Capture::MediaStreamType DefaultStreamType = Windows::Media::Capture::MediaStreamType::VideoRecord;
static constexpr bool DefaultHologramCompositionEnabled = true;
@@ -178,8 +267,12 @@ namespace MrcEffectDefinitions
static constexpr bool DefaultVideoStabilizationEnabled = false;
static constexpr uint32_t DefaultVideoStabilizationBufferLength = 0U;
static constexpr float DefaultGlobalOpacityCoefficient = 0.9f;
+ static constexpr bool DefaultBlankOnProtectedContent = false;
+ static constexpr bool DefaultShowHiddenMesh = false;
+ static constexpr MixedRealityCapturePerspective DefaultPreferredHologramPerspective = MixedRealityCapturePerspective::PhotoVideoCamera;
private:
Platform::String^ m_activatableClassId = ref new Platform::String(RUNTIMECLASS_MIXEDREALITYCAPTURE_VIDEO_EFFECT);
Windows::Foundation::Collections::PropertySet^ m_propertySet = ref new Windows::Foundation::Collections::PropertySet();
+ Windows::Foundation::Size DefaultOutputSize = { 0,0 };
};
}
diff --git a/Samples/HttpClient/HttpFilters/HttpFilters.def b/Samples/HttpClient/HttpFilters/HttpFilters.def
new file mode 100644
index 0000000000..24e7c1235c
--- /dev/null
+++ b/Samples/HttpClient/HttpFilters/HttpFilters.def
@@ -0,0 +1,3 @@
+EXPORTS
+DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj b/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj
index ab56e0cff4..85ec281cbb 100644
--- a/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj
+++ b/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj
@@ -1,10 +1,32 @@

-
+
+
+
+ true
+ true
+ true
+ true
+ {b31fb521-eba9-5a64-93d7-4675dae9845b}
+ HttpFilters
+ HttpFilters
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.18362.0
+ 10.0.18362.0
+
+
Debug
ARM
+
+ Debug
+ ARM64
+
Debug
Win32
@@ -17,6 +39,10 @@
Release
ARM
+
+ Release
+ ARM64
+
Release
Win32
@@ -26,187 +52,67 @@
x64
-
- $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), LICENSE))\SharedContent
-
-
- {afb1caf8-88c3-5b4f-ab1f-05c403e37a9e}
- Win32Proj
- HttpFilters
- HttpFilters
- en-US
- 14.0
- true
- Windows Store
- 10.0
- 10.0.18362.0
- 10.0.18362.0
- true
-
-
-
+
DynamicLibrary
- true
-
-
- DynamicLibrary
- true
+ v140
+ v141
+ v142
+ Unicode
+ false
-
- DynamicLibrary
+
true
+ true
-
- DynamicLibrary
- false
- true
- true
-
-
- DynamicLibrary
+
false
true
- true
-
-
- DynamicLibrary
- false
- true
- true
+ false
-
-
+
-
-
+
-
+
-
-
-
-
-
-
-
-
+
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
+
Use
- _WINRT_DLL;%(PreprocessorDefinitions)
pch.h
$(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+
+ /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)
+
+
+ _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)
$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
- /bigobj %(AdditionalOptions)
- 28204
Console
- runtimeobject.lib;%(AdditionalDependencies)
- false
+ false
+ HttpFilters.def
-
+
- Use
- _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
- pch.h
- $(IntDir)pch.pch
- $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
- /bigobj %(AdditionalOptions)
- 28204
+ _DEBUG;%(PreprocessorDefinitions)
-
- Console
- runtimeobject.lib;%(AdditionalDependencies)
- false
-
-
+
- Use
- _WINRT_DLL;%(PreprocessorDefinitions)
- pch.h
- $(IntDir)pch.pch
- $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
- /bigobj %(AdditionalOptions)
- 28204
+ NDEBUG;%(PreprocessorDefinitions)
- Console
- runtimeobject.lib;%(AdditionalDependencies)
- false
-
-
-
-
- Use
- _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
- pch.h
- $(IntDir)pch.pch
- $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
- /bigobj %(AdditionalOptions)
- 28204
-
-
- Console
- runtimeobject.lib;%(AdditionalDependencies)
- false
-
-
-
-
- Use
- _WINRT_DLL;%(PreprocessorDefinitions)
- pch.h
- $(IntDir)pch.pch
- $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
- /bigobj %(AdditionalOptions)
- 28204
-
-
- Console
- runtimeobject.lib;%(AdditionalDependencies)
- false
-
-
-
-
- Use
- _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
- pch.h
- $(IntDir)pch.pch
- $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
- /bigobj %(AdditionalOptions)
- 28204
-
-
- Console
- runtimeobject.lib;%(AdditionalDependencies)
- false
+ true
+ true
@@ -218,15 +124,26 @@
- Create
- Create
- Create
- Create
- Create
- Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj.filters b/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj.filters
index 3ef172ed6a..20c290be92 100644
--- a/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj.filters
+++ b/Samples/HttpClient/HttpFilters/HttpFilters.vcxproj.filters
@@ -1,13 +1,17 @@

-
+
- 180439cf-c61b-4620-85cb-459fa637968f
+ accd3aa8-1ba0-4223-9bbe-0c431709210b
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+ {926ab91d-31b4-48c3-b9a4-e681349f27f0}
+
+
@@ -16,4 +20,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.cpp b/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.cpp
index 8441c4223a..2f8bdc6913 100644
--- a/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.cpp
+++ b/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.cpp
@@ -11,125 +11,108 @@
#include "pch.h"
#include "HttpMeteredConnectionFilter.h"
-#include
-#include
+#include "HttpMeteredConnectionFilter.g.cpp"
-using namespace Concurrency;
-using namespace HttpFilters;
-using namespace Platform;
-using namespace Windows::Foundation;
-using namespace Windows::Networking::Connectivity;
-using namespace Windows::Web::Http;
-using namespace Windows::Web::Http::Filters;
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Networking::Connectivity;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
-String^ HttpMeteredConnectionFilter::PriorityPropertyName = ref new String(L"meteredConnectionPriority");
-
-HttpMeteredConnectionFilter::HttpMeteredConnectionFilter(IHttpFilter^ innerFilter)
+namespace winrt::HttpFilters::implementation
{
- if (innerFilter == nullptr)
+ HttpMeteredConnectionFilter::HttpMeteredConnectionFilter(IHttpFilter const& innerFilter) : m_innerFilter(innerFilter)
{
- throw ref new Exception(E_INVALIDARG, "innerFilter cannot be null.");
+ if (!m_innerFilter)
+ {
+ throw hresult_invalid_argument(L"innerFilter cannot be null.");
+ }
}
- this->innerFilter = innerFilter;
-}
-HttpMeteredConnectionFilter::~HttpMeteredConnectionFilter()
-{
-}
-
-IAsyncOperationWithProgress^ HttpMeteredConnectionFilter::SendRequestAsync(
- HttpRequestMessage^ request)
-{
- MeteredConnectionPriority priority = MeteredConnectionPriority::Low;
- if (request->Properties->HasKey(PriorityPropertyName))
+ IAsyncOperationWithProgress HttpMeteredConnectionFilter::SendRequestAsync(HttpRequestMessage request)
{
- Object^ value = request->Properties->Lookup(PriorityPropertyName);
- IPropertyValue^ propertyValue = static_cast(value);
+ auto lifetime = get_strong();
- if (propertyValue->Type == PropertyType::Double)
+ MeteredConnectionPriority priority = MeteredConnectionPriority::Low;
+ auto value = request.Properties().TryLookup(MeteredConnectionPriorityPropertyNameLiteral).try_as();
+ if (value)
{
- // Enum values in JS are stored as double values.
- unsigned int intValue = static_cast(propertyValue->GetDouble());
- priority = static_cast(intValue) ;
+ if (value.Type() == PropertyType::Double)
+ {
+ // Numeric values in JavaScript are represented as doubles.
+ priority = static_cast(value.GetDouble());
+ }
+ else
+ {
+ priority = unbox_value_or(value, MeteredConnectionPriority::Low);
+ }
}
- else
- {
- // A static cast is enough when value comes from C# or C++.
- priority = static_cast(value);
- }
- }
- if (!ValidatePriority(priority))
- {
- throw ref new Exception(E_ACCESSDENIED, "The request priority is not allowed under the current connection behavior.");
- }
+ CheckPriority(priority);
- return innerFilter->SendRequestAsync(request);
-}
+ return m_innerFilter.SendRequestAsync(request);
+ }
-bool HttpMeteredConnectionFilter::OptIn::get()
-{
- return optIn;
-}
+ void HttpMeteredConnectionFilter::CheckPriority(MeteredConnectionPriority priority)
+ {
+ MeteredConnectionBehavior behavior = GetBehavior();
-void HttpMeteredConnectionFilter::OptIn::set(bool value)
-{
- optIn = value;
-}
+ switch (behavior)
+ {
+ case MeteredConnectionBehavior::Normal:
+ // Under normal behavior all requests are allowed.
+ return;
+
+ case MeteredConnectionBehavior::Conservative:
+ // Under conservative behavior all requests except low priority requests are allowed.
+ if (priority != MeteredConnectionPriority::Low)
+ {
+ return;
+ }
+ break;
+
+ case MeteredConnectionBehavior::OptIn:
+ // Under opt-in only high priority requests are allowed and only if user opted in.
+ if (priority == MeteredConnectionPriority::High && OptIn())
+ {
+ return;
+ }
+ break;
+ }
-bool HttpMeteredConnectionFilter::ValidatePriority(MeteredConnectionPriority priority)
-{
- MeteredConnectionBehavior behavior = GetBehavior();
+ // Everything else is not allowed.
+ throw hresult_access_denied(L"The request priority is not allowed under the current connection behavior.");
+ }
- switch (behavior)
+ HttpMeteredConnectionFilter::MeteredConnectionBehavior HttpMeteredConnectionFilter::GetBehavior()
{
- case MeteredConnectionBehavior::Normal:
- // Under normal behavior all requests are allowed.
- return true;
- case MeteredConnectionBehavior::Conservative:
- // Under conservative behavior all requests except low priority requests are allowed.
- if (priority != MeteredConnectionPriority::Low)
- {
- return true;
- }
- break;
- case MeteredConnectionBehavior::OptIn:
- // Under opt-in only high priority requests are allowed and only if user opted in.
- if (priority == MeteredConnectionPriority::High && OptIn)
+ ConnectionProfile connectionProfile = NetworkInformation::GetInternetConnectionProfile();
+
+ if (connectionProfile == nullptr)
{
- return true;
+ return MeteredConnectionBehavior::None;
}
- break;
- }
- // Everything else is not allowed.
- return false;
-}
+ ConnectionCost connectionCost = connectionProfile.GetConnectionCost();
-MeteredConnectionBehavior HttpMeteredConnectionFilter::GetBehavior()
-{
- ConnectionProfile^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
+ if (connectionCost.Roaming())
+ {
+ return MeteredConnectionBehavior::OptIn;
+ }
- if (connectionProfile == nullptr)
- {
- return MeteredConnectionBehavior::None;
- }
+ NetworkCostType type = connectionCost.NetworkCostType();
+ if (type == NetworkCostType::Unrestricted || type == NetworkCostType::Unknown)
+ {
+ return MeteredConnectionBehavior::Normal;
+ }
- ConnectionCost^ connectionCost = connectionProfile->GetConnectionCost();
+ else if (!connectionCost.OverDataLimit() && (type == NetworkCostType::Fixed || type == NetworkCostType::Variable))
+ {
+ return MeteredConnectionBehavior::Conservative;
+ }
- if (!connectionCost->Roaming &&
- (connectionCost->NetworkCostType == NetworkCostType::Unrestricted ||
- connectionCost->NetworkCostType == NetworkCostType::Unknown))
- {
- return MeteredConnectionBehavior::Normal;
- }
- else if (!connectionCost->Roaming &&
- !connectionCost->OverDataLimit &&
- (connectionCost->NetworkCostType == NetworkCostType::Fixed ||
- connectionCost->NetworkCostType == NetworkCostType::Variable))
- {
- return MeteredConnectionBehavior::Conservative;
+ return MeteredConnectionBehavior::OptIn;
}
- return MeteredConnectionBehavior::OptIn;
}
diff --git a/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.h b/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.h
index d76a0f1664..0db8d88a0c 100644
--- a/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.h
+++ b/Samples/HttpClient/HttpFilters/HttpMeteredConnectionFilter.h
@@ -10,46 +10,43 @@
//*********************************************************
#pragma once
+#include "HttpMeteredConnectionFilter.g.h"
+using namespace winrt;
-namespace HttpFilters
+namespace winrt::HttpFilters::implementation
{
- public enum class MeteredConnectionPriority
+ struct HttpMeteredConnectionFilter : HttpMeteredConnectionFilterT
{
- Low = 0,
- Medium,
- High
- };
+ HttpMeteredConnectionFilter(Windows::Web::Http::Filters::IHttpFilter const& innerFilter);
+ bool OptIn() { return m_optIn; }
+ void OptIn(bool value) { m_optIn = value; }
+ void Close() { }
+ Windows::Foundation::IAsyncOperationWithProgress SendRequestAsync(Windows::Web::Http::HttpRequestMessage request);
- private enum class MeteredConnectionBehavior
- {
- None = 0, // Used when there is no Internet profile available.
- Normal,
- Conservative,
- OptIn
- };
+ static hstring MeteredConnectionPriorityPropertyName() { return MeteredConnectionPriorityPropertyNameLiteral; }
- public ref class HttpMeteredConnectionFilter sealed : public Windows::Web::Http::Filters::IHttpFilter
- {
- public:
- HttpMeteredConnectionFilter(Windows::Web::Http::Filters::IHttpFilter^ innerFilter);
- virtual ~HttpMeteredConnectionFilter();
- virtual Windows::Foundation::IAsyncOperationWithProgress<
- Windows::Web::Http::HttpResponseMessage^,
- Windows::Web::Http::HttpProgress>^ SendRequestAsync(Windows::Web::Http::HttpRequestMessage^ request);
-
- property bool OptIn
+ private:
+ enum class MeteredConnectionBehavior
{
- bool get();
- void set(bool value);
- }
+ None = 0, // Used when there is no Internet profile available.
+ Normal,
+ Conservative,
+ OptIn
+ };
+
+ static constexpr wchar_t MeteredConnectionPriorityPropertyNameLiteral[] = L"HttpFilters.HttpMeteredConnectionFilter.MeteredConnectionPriority";
- private:
- Windows::Web::Http::Filters::IHttpFilter^ innerFilter;
- bool ValidatePriority(MeteredConnectionPriority priority);
- MeteredConnectionBehavior GetBehavior();
+ Windows::Web::Http::Filters::IHttpFilter m_innerFilter;
+ bool m_optIn;
- bool optIn;
- static Platform::String^ PriorityPropertyName;
+ static MeteredConnectionBehavior GetBehavior();
+ void CheckPriority(MeteredConnectionPriority priority);
+ };
+}
+namespace winrt::HttpFilters::factory_implementation
+{
+ struct HttpMeteredConnectionFilter : HttpMeteredConnectionFilterT
+ {
};
}
diff --git a/Samples/HttpClient/HttpFilters/HttpRetryFilter.cpp b/Samples/HttpClient/HttpFilters/HttpRetryFilter.cpp
index 88f7b771cb..4359733320 100644
--- a/Samples/HttpClient/HttpFilters/HttpRetryFilter.cpp
+++ b/Samples/HttpClient/HttpFilters/HttpRetryFilter.cpp
@@ -1,4 +1,4 @@
-//*********************************************************
+//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
@@ -9,199 +9,108 @@
//
//*********************************************************
-// Class1.cpp
#include "pch.h"
#include "HttpRetryFilter.h"
-#include
-#include
-#include
-#include
-
-using namespace Concurrency;
-using namespace HttpFilters;
-using namespace Platform;
-using namespace Windows::Foundation;
-using namespace Windows::Foundation::Collections;
-using namespace Windows::Web::Http;
-using namespace Windows::Web::Http::Filters;
-
-String^ HttpRetryFilter::RetriesPropertyName = ref new String(L"retries");
-long long const HttpRetryFilter::TicksPerSecond = 10000000; // 100-nanoseconds in one second.
-
-HttpRetryFilter::HttpRetryFilter(IHttpFilter^ innerFilter)
+#include "HttpRetryFilter.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+using namespace winrt::Windows::Web::Http::Headers;
+
+namespace winrt::HttpFilters::implementation
{
- if (innerFilter == nullptr)
+ HttpRetryFilter::HttpRetryFilter(IHttpFilter const& innerFilter) : m_innerFilter(innerFilter)
{
- throw ref new Exception(E_INVALIDARG, "innerFilter cannot be null.");
+ if (!m_innerFilter)
+ {
+ throw hresult_invalid_argument(L"innerFilter cannot be null.");
+ }
}
- this->innerFilter = innerFilter;
-}
-HttpRetryFilter::~HttpRetryFilter()
-{
-}
+ uint32_t HttpRetryFilter::GetRetriesValue(HttpRequestMessage const& request)
+ {
+ // Retries property keeps the number of times the request has been resent.
+ return unbox_value_or(request.Properties().TryLookup(RetriesPropertyName), 0U);
+ }
-IAsyncOperationWithProgress^ HttpRetryFilter::SendRequestAsync(
- HttpRequestMessage^ request)
-{
- return create_async([=](progress_reporter reporter, cancellation_token token)
+ HttpRequestMessage HttpRetryFilter::CopyRequestMessage(HttpRequestMessage const& request)
{
- // Propagate progress. Increment HttpProgress.Retries by the number of times we have resent the request.
- unsigned int retries = GetRetriesProperty(request);
- IAsyncOperationWithProgress^ operation = innerFilter->SendRequestAsync(request);
- operation->Progress = ref new AsyncOperationProgressHandler([=](
- IAsyncOperationWithProgress^ asyncInfo,
- HttpProgress progress)
- {
- progress.Retries += retries;
- reporter.report(progress);
- });
+ HttpRequestMessage copy(request.Method(), request.RequestUri());
- return create_task(operation, token).then([=](task sendRequestTask)
+ // Copy the headers.
+ HttpRequestHeaderCollection headers = copy.Headers();
+ for (auto [key, value] : request.Headers())
{
- HttpResponseMessage^ response = sendRequestTask.get();
-
- // Check if response has a 503 status code.
- if (response->StatusCode != HttpStatusCode::ServiceUnavailable)
+ if (!headers.TryAppendWithoutValidation(key, value))
{
- return sendRequestTask;
+ throw hresult_error(E_FAIL, L"Unable to copy headers.");
}
+ }
- // Check if response has a Retry-After header.
- if (!response->Headers->RetryAfter)
- {
- return sendRequestTask;
- }
+ // Copy the properties.
+ IMap properties = copy.Properties();
+ for (auto [key, value] : request.Properties())
+ {
+ properties.Insert(key, value);
+ }
+
+ // Increment the retry count.
+ properties.Insert(RetriesPropertyName, box_value(GetRetriesValue(request) + 1));
+
+ return copy;
+ }
+
+ IAsyncOperationWithProgress HttpRetryFilter::SendRequestAsync(HttpRequestMessage request)
+ {
+ auto lifetime = get_strong();
+ auto progress = co_await get_progress_token();
- long long deltaSeconds;
- if (response->Headers->RetryAfter->Delta)
+ while (true)
+ {
+ // Propagate progress. Increment HttpProgress.Retries by the number of times we have resent the request.
+ IAsyncOperationWithProgress operation = m_innerFilter.SendRequestAsync(request);
+ operation.Progress([progress, retries = GetRetriesValue(request)](auto&&, HttpProgress data) mutable
+ {
+ data.Retries += retries;
+ progress(data);
+ });
+
+ HttpResponseMessage response = co_await operation;
+
+ // Retry requires 503 status code.
+ if (response.StatusCode() != HttpStatusCode::ServiceUnavailable)
{
- TimeSpan delta = response->Headers->RetryAfter->Delta->Value;
- deltaSeconds = delta.Duration / TicksPerSecond;
+ co_return response;
}
- else if (response->Headers->RetryAfter->Date)
- {
- DateTime retryDateTime = response->Headers->RetryAfter->Date->Value;
- DateTime currentDateTime = GetCurrentUtcDateTime();
- deltaSeconds = (retryDateTime.UniversalTime - currentDateTime.UniversalTime) / TicksPerSecond;
- }
- else
+ // Retry requires Retry-After header.
+ HttpDateOrDeltaHeaderValue retryAfter = response.Headers().RetryAfter();
+ if (!retryAfter)
{
- return sendRequestTask;
+ co_return response;
}
- // If the difference is negative, it means the Retry-After date was in the past.
- if (deltaSeconds < 0)
+ TimeSpan delay;
+ if (auto delta = retryAfter.Delta())
{
- deltaSeconds = 0;
+ delay = delta.Value();
}
-
- if (deltaSeconds > INT_MAX)
+ else if (auto date = retryAfter.Date())
{
- deltaSeconds = INT_MAX;
+ delay = date.Value() - clock::now();
}
-
- return DelayAsync(static_cast(deltaSeconds), response).then(
- [=](task delayTask)
+ else
{
- HttpRequestMessage^ requestCopy = CopyRequestMessage(request);
- return create_task(SendRequestAsync(requestCopy), token);
- }, token);
- }, token);
- });
-}
-
-Concurrency::task HttpRetryFilter::DelayAsync(
- unsigned int deltaSeconds,
- HttpResponseMessage^ response)
-{
- // A task completion event that is set when a timer fires.
- task_completion_event tce;
-
- // Create a non-repeating timer.
- std::shared_ptr> fire_once(new timer(deltaSeconds * 1000, 0, nullptr, false));
-
- // Create a call object that sets the completion event after the timer fires.
- std::shared_ptr> callback(new call([=](int)
- {
- tce.set(response);
- }));
-
- // Connect the timer to the callback and start the timer.
- fire_once->link_target(callback.get());
- fire_once->start();
-
- // Create a task that completes after the completion event is set.
- task event_set(tce);
-
- // Create a continuation task that cleans up resources and return that continuation task.
- return event_set.then([callback, fire_once](HttpResponseMessage^ response)
- {
- return response;
- });
-}
-
-DateTime HttpRetryFilter::GetCurrentUtcDateTime()
-{
- SYSTEMTIME currentSystemTime;
- GetSystemTime(¤tSystemTime);
-
- FILETIME currentFileTime;
- if (!SystemTimeToFileTime(¤tSystemTime, ¤tFileTime))
- {
- throw ref new Exception(HRESULT_FROM_WIN32(GetLastError()));
- }
-
- ULARGE_INTEGER currentLargeInteger = {currentFileTime.dwLowDateTime, currentFileTime.dwHighDateTime};
-
- DateTime currentDateTime;
- currentDateTime.UniversalTime = currentLargeInteger.QuadPart;
-
- return currentDateTime;
-}
+ co_return response;
+ }
-HttpRequestMessage^ HttpRetryFilter::CopyRequestMessage(HttpRequestMessage^ request)
-{
- HttpRequestMessage^ copy = ref new HttpRequestMessage(request->Method, request->RequestUri);
+ co_await resume_after(delay);
- IIterator^>^ headerIterator = request->Headers->First();
- while (headerIterator->HasCurrent)
- {
- IKeyValuePair^ header = headerIterator->Current;
- String^ key = header->Key;
- String^ value = header->Value;
- bool result = copy->Headers->TryAppendWithoutValidation(key, value);
- if (!result)
- {
- throw ref new Exception(E_FAIL, "Unable to copy headers.");
+ // Try again with a new request.
+ request = CopyRequestMessage(request);
}
- headerIterator->MoveNext();
- }
-
- IIterator^>^ propertiesIterator = request->Properties->First();
- while (propertiesIterator->HasCurrent)
- {
- IKeyValuePair^ header = propertiesIterator->Current;
- String^ key = header->Key;
- Object^ value = header->Value;
- copy->Properties->Insert(key, value);
- propertiesIterator->MoveNext();
- }
-
- // Increment retries property by one.
- copy->Properties->Insert(RetriesPropertyName, GetRetriesProperty(copy) + 1);
-
- return copy;
-}
-
-unsigned int HttpRetryFilter::GetRetriesProperty(Windows::Web::Http::HttpRequestMessage^ request)
-{
- // Retries property keeps the number of times the request has been resent.
- unsigned int retries = 0;
- if (request->Properties->HasKey(RetriesPropertyName))
- {
- retries = static_cast(request->Properties->Lookup(RetriesPropertyName));
}
- return retries;
}
diff --git a/Samples/HttpClient/HttpFilters/HttpRetryFilter.h b/Samples/HttpClient/HttpFilters/HttpRetryFilter.h
index 83eb2dad06..15171b8b57 100644
--- a/Samples/HttpClient/HttpFilters/HttpRetryFilter.h
+++ b/Samples/HttpClient/HttpFilters/HttpRetryFilter.h
@@ -1,4 +1,4 @@
-//*********************************************************
+//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
@@ -10,30 +10,27 @@
//*********************************************************
#pragma once
+#include "HttpRetryFilter.g.h"
-#include
-
-namespace HttpFilters
+namespace winrt::HttpFilters::implementation
{
- public ref class HttpRetryFilter sealed : public Windows::Web::Http::Filters::IHttpFilter
+ struct HttpRetryFilter : HttpRetryFilterT
{
- public:
- HttpRetryFilter(Windows::Web::Http::Filters::IHttpFilter^ innerFilter);
- virtual ~HttpRetryFilter();
- virtual Windows::Foundation::IAsyncOperationWithProgress<
- Windows::Web::Http::HttpResponseMessage^,
- Windows::Web::Http::HttpProgress>^ SendRequestAsync(Windows::Web::Http::HttpRequestMessage^ request);
+ HttpRetryFilter(Windows::Web::Http::Filters::IHttpFilter const& innerFilter);
+ void Close() {}
+ Windows::Foundation::IAsyncOperationWithProgress SendRequestAsync(Windows::Web::Http::HttpRequestMessage request);
private:
- Concurrency::task DelayAsync(
- unsigned int deltaSeconds,
- Windows::Web::Http::HttpResponseMessage^ response);
- Windows::Foundation::DateTime GetCurrentUtcDateTime();
- Windows::Web::Http::HttpRequestMessage^ CopyRequestMessage(Windows::Web::Http::HttpRequestMessage^ request);
- unsigned int GetRetriesProperty(Windows::Web::Http::HttpRequestMessage^ request);
+ Windows::Web::Http::Filters::IHttpFilter m_innerFilter;
- Windows::Web::Http::Filters::IHttpFilter^ innerFilter;
- static Platform::String^ RetriesPropertyName;
- static long long const TicksPerSecond;
+ static constexpr wchar_t RetriesPropertyName[] = L"HttpFilters.HttpRetryFilter.Retries";
+ static uint32_t GetRetriesValue(Windows::Web::Http::HttpRequestMessage const& request);
+ static Windows::Web::Http::HttpRequestMessage CopyRequestMessage(Windows::Web::Http::HttpRequestMessage const& message);
+ };
+}
+namespace winrt::HttpFilters::factory_implementation
+{
+ struct HttpRetryFilter : HttpRetryFilterT
+ {
};
}
diff --git a/Samples/HttpClient/HttpFilters/Project.idl b/Samples/HttpClient/HttpFilters/Project.idl
new file mode 100644
index 0000000000..02244924d9
--- /dev/null
+++ b/Samples/HttpClient/HttpFilters/Project.idl
@@ -0,0 +1,21 @@
+namespace HttpFilters
+{
+ enum MeteredConnectionPriority
+ {
+ Low = 0,
+ Medium,
+ High
+ };
+
+ runtimeclass HttpRetryFilter : [default] Windows.Web.Http.Filters.IHttpFilter
+ {
+ HttpRetryFilter(Windows.Web.Http.Filters.IHttpFilter innerFilter);
+ }
+
+ runtimeclass HttpMeteredConnectionFilter : [default] Windows.Web.Http.Filters.IHttpFilter
+ {
+ HttpMeteredConnectionFilter(Windows.Web.Http.Filters.IHttpFilter innerFilter);
+ Boolean OptIn;
+ static String MeteredConnectionPriorityPropertyName{ get; };
+ }
+}
diff --git a/Samples/HttpClient/HttpFilters/packages.config b/Samples/HttpClient/HttpFilters/packages.config
new file mode 100644
index 0000000000..3407555859
--- /dev/null
+++ b/Samples/HttpClient/HttpFilters/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/HttpFilters/pch.cpp b/Samples/HttpClient/HttpFilters/pch.cpp
index dc586a230a..bcb5590be1 100644
--- a/Samples/HttpClient/HttpFilters/pch.cpp
+++ b/Samples/HttpClient/HttpFilters/pch.cpp
@@ -1,11 +1 @@
-//*********************************************************
-//
-// Copyright (c) Microsoft. All rights reserved.
-// This code is licensed under the MIT License (MIT).
-// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
-// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
-// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
-// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
-//
-//*********************************************************
-#include "pch.h"
+#include "pch.h"
diff --git a/Samples/HttpClient/HttpFilters/pch.h b/Samples/HttpClient/HttpFilters/pch.h
index d05a6bfdcb..f444712782 100644
--- a/Samples/HttpClient/HttpFilters/pch.h
+++ b/Samples/HttpClient/HttpFilters/pch.h
@@ -1,15 +1,8 @@
-//*********************************************************
-//
-// Copyright (c) Microsoft. All rights reserved.
-// This code is licensed under the MIT License (MIT).
-// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
-// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
-// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
-// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
-//
-//*********************************************************
-
-#pragma once
-
-#include
-#include
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+#include
diff --git a/Samples/HttpClient/README.md b/Samples/HttpClient/README.md
index 3261b2c64f..aa6db57ed4 100644
--- a/Samples/HttpClient/README.md
+++ b/Samples/HttpClient/README.md
@@ -3,7 +3,7 @@ page_type: sample
languages:
- csharp
- cpp
-- cppcx
+- cppwinrt
products:
- windows
- windows-uwp
@@ -100,16 +100,6 @@ For more information on network capabilities, see [How to set network capabiliti
[Networking basics](https://msdn.microsoft.com/library/windows/apps/mt280233)
[Troubleshooting and debugging network connections](http://msdn.microsoft.com/library/windows/apps/hh770534)
-### Other - JavaScript and HTML
-
-[Adding support for networking (HTML)](http://msdn.microsoft.com/library/windows/apps/hh452752)
-[Connecting to network services (HTML)](http://msdn.microsoft.com/library/windows/apps/hh452977)
-[Connecting with WebSockets (HTML)](http://msdn.microsoft.com/library/windows/apps/hh761442)
-[How to connect to an HTTP server using Windows.Web.Http (HTML)](http://msdn.microsoft.com/library/windows/apps/dn469430)
-[How to set background connectivity options (HTML)](http://msdn.microsoft.com/library/windows/apps/hh771189)
-[How to set network capabilities (HTML)](http://msdn.microsoft.com/library/windows/apps/hh770532)
-[Troubleshooting and debugging network connections](http://msdn.microsoft.com/library/windows/apps/hh770534)
-
### Other resources
[Adding support for networking](http://msdn.microsoft.com/library/windows/apps/hh452752)
@@ -118,6 +108,10 @@ For more information on network capabilities, see [How to set network capabiliti
[How to secure HttpClient connections](http://msdn.microsoft.com/library/windows/apps/hh781240)
[Quickstart: Connecting using HttpClient](http://msdn.microsoft.com/library/windows/apps/hh781239)
+### Other samples
+
+[HttpClient](/archived/HttpClient/) for C++/CX and VB (archived)
+
### Reference
[HttpClient](http://msdn.microsoft.com/library/windows/apps/dn298639)
@@ -127,11 +121,9 @@ For more information on network capabilities, see [How to set network capabiliti
## System requirements
-**Client:** Windows 10 version 1604 preview
-
-**Server:** Windows Server 2016 Technical Preview
+**Client:** Windows 10 version 1903
-**Phone:** Windows 10 version 1604 preview
+**Server:** Windows Server Version 1903
## Build the sample
diff --git a/Samples/HttpClient/cppwinrt/Helpers.cpp b/Samples/HttpClient/cppwinrt/Helpers.cpp
new file mode 100644
index 0000000000..90bb13375d
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Helpers.cpp
@@ -0,0 +1,164 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include
+#include "MainPage.h"
+#include "SampleConfiguration.h"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::Web;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+using namespace winrt::Windows::Web::Http::Headers;
+
+namespace winrt::SDKTemplate::Helpers
+{
+ hstring ToSimpleString(Windows::Foundation::DateTime dateTime)
+ {
+ auto time = clock::to_time_t(dateTime);
+ char buffer[26];
+ ctime_s(buffer, ARRAYSIZE(buffer), &time);
+ buffer[25] = 0; // remove the trailing newline
+ return to_hstring(buffer);
+ }
+
+ IAsyncAction DisplayTextResultAsync(HttpResponseMessage response, TextBox output)
+ {
+ output.Text(output.Text() + SerializeHeaders(response));
+
+ auto cancellation = co_await get_cancellation_token();
+ auto operation = response.Content().ReadAsStringAsync();
+ cancellation.callback([operation] { operation.Cancel(); });
+ std::wstring text{ co_await operation };
+
+ // Change to newlines.
+ for (auto pos = text.find(L" "); pos != std::wstring::npos; pos = text.find(L" ", pos + 1))
+ {
+ text.replace(pos, 4, L"\n");
+ }
+
+ output.Text(output.Text() + hstring(text));
+ }
+
+ hstring SerializeHeaders(HttpResponseMessage const& response)
+ {
+ std::wostringstream output;
+
+ auto SerializeHeaderCollection = [&](IIterable> const& headers)
+ {
+ for (auto [key, value] : headers)
+ {
+ output << std::wstring_view(key) << L": " << std::wstring_view(value) << L"\n";
+ }
+ };
+
+ // We cast the StatusCode to an int so we display the numeric value (e.g., "200") rather than the
+ // name of the enum (e.g., "OK") which would often be redundant with the ReasonPhrase.
+
+ output << static_cast(response.StatusCode()) << L" " << std::wstring_view(response.ReasonPhrase()) << L"\n";
+
+ SerializeHeaderCollection(response.Headers());
+ SerializeHeaderCollection(response.Content().Headers());
+ output << L"\n";
+ return hstring(output.str());
+ }
+
+ void DisplayWebError(MainPage const& rootPage, hresult const& error)
+ {
+ WebErrorStatus webErrorStatus = WebError::GetStatus(error);
+ if (webErrorStatus == WebErrorStatus::Unknown)
+ {
+ rootPage.NotifyUser(L"Unknown Error: " + hresult_error(error).message(), NotifyType::ErrorMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser(L"Web Error: " + to_hstring(webErrorStatus), NotifyType::ErrorMessage);
+ }
+
+ }
+
+ HttpClient CreateHttpClientWithCustomHeaders()
+ {
+ // HttpClient functionality can be extended by plugging multiple filters together and providing
+ // HttpClient with the configured filter pipeline.
+ IHttpFilter filter = HttpBaseProtocolFilter();
+ filter = PlugInFilter(filter); // Adds a custom header to every request and response message.
+ HttpClient httpClient(filter);
+
+ // The following line sets a "User-Agent" request header as a default header on the HttpClient instance.
+ // Default headers will be sent with every request sent from this HttpClient instance.
+ httpClient.DefaultRequestHeaders().UserAgent().Append(HttpProductInfoHeaderValue(L"Sample", L"v8"));
+
+ return httpClient;
+ }
+
+ void ScenarioStarted(Button const& startButton, Button const& cancelButton, TextBox const& outputField)
+ {
+ startButton.IsEnabled(false);
+ cancelButton.IsEnabled(true);
+ if (outputField != nullptr)
+ {
+ outputField.Text(L"");
+ }
+ }
+
+ void ScenarioCompleted(Button const& startButton, Button const& cancelButton)
+ {
+ startButton.IsEnabled(true);
+ cancelButton.IsEnabled(false);
+ }
+
+ void ReplaceQueryString(TextBox const& addressField, hstring const& newQueryString)
+ {
+ hstring resourceAddress = addressField.Text();
+ std::wstring_view view(resourceAddress);
+
+ // Remove previous query string.
+ auto questionMarkPos = view.find(L'?');
+ if (questionMarkPos != std::wstring_view::npos)
+ {
+ view = view.substr(0, questionMarkPos);
+ }
+
+ addressField.Text(view + newQueryString);
+ }
+
+ Uri TryParseHttpUri(hstring const& uriString)
+ {
+ // Note that this app has both "Internet (Client)" and "Home and Work Networking" capabilities set,
+ // since the user may provide URIs for servers located on the internet or intranet. If apps only
+ // communicate with servers on the internet, only the "Internet (Client)" capability should be set.
+ // Similarly if an app is only intended to communicate on the intranet, only the "Home and Work
+ // Networking" capability should be set.
+ try
+ {
+ Uri uri(uriString);
+ hstring scheme = uri.SchemeName();
+ if (scheme == L"http" || scheme == L"https")
+ {
+ return uri;
+ }
+ }
+ catch (hresult_error const& ex)
+ {
+ if (ex.code() != E_POINTER && ex.code() != E_INVALIDARG)
+ {
+ throw;
+ }
+ }
+ return nullptr;
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Helpers.h b/Samples/HttpClient/cppwinrt/Helpers.h
new file mode 100644
index 0000000000..75d9e06284
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Helpers.h
@@ -0,0 +1,63 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace winrt::SDKTemplate::Helpers
+{
+ // This helper function is a convenience wrapper to make it
+ // easier to allow a coroutine to propagate cancel
+ // requests into asynchronous operations that it is awaiting.
+ //
+ // Without this helper function, you write
+ //
+ // auto cancellation = co_await get_cancellation_token();
+ // auto operation = SomethingAsync();
+ // cancellation.callback([operation] { operation.Cancel(); });
+ // auto result = co_await operation;
+ //
+ // With this helper, you write
+ //
+ // auto cancellation = co_await get_cancellation_token();
+ // auto result = co_await AddCancellation(SomethingAsync(), cancellation);
+ //
+ template
+ auto AddCancellation(Async&& async, Token&& token)
+ {
+ token.callback([async] { async.Cancel(); });
+ return std::forward(async);
+ }
+
+ hstring ToSimpleString(Windows::Foundation::DateTime time);
+
+ Windows::Foundation::IAsyncAction DisplayTextResultAsync(
+ Windows::Web::Http::HttpResponseMessage response,
+ Windows::UI::Xaml::Controls::TextBox output);
+
+ void DisplayWebError(MainPage const& rootPage, hresult const& exception);
+
+ hstring SerializeHeaders(Windows::Web::Http::HttpResponseMessage const& response);
+
+ Windows::Web::Http::HttpClient CreateHttpClientWithCustomHeaders();
+
+ void ScenarioStarted(
+ Windows::UI::Xaml::Controls::Button const& startButton,
+ Windows::UI::Xaml::Controls::Button const& cancelButton,
+ Windows::UI::Xaml::Controls::TextBox const& outputField);
+
+ void ScenarioCompleted(
+ Windows::UI::Xaml::Controls::Button const& startButton,
+ Windows::UI::Xaml::Controls::Button const& cancelButton);
+
+ void ReplaceQueryString(Windows::UI::Xaml::Controls::TextBox const& addressField, hstring const& newQueryString);
+ Windows::Foundation::Uri TryParseHttpUri(hstring const& uriString);
+}
diff --git a/Samples/HttpClient/cppwinrt/HttpClient.sln b/Samples/HttpClient/cppwinrt/HttpClient.sln
new file mode 100644
index 0000000000..4967d32628
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/HttpClient.sln
@@ -0,0 +1,65 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29920.165
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpClient", "HttpClient.vcxproj", "{D2975110-E20D-5AC1-B6B1-4F544475362A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpFilters", "..\HttpFilters\HttpFilters.vcxproj", "{87FB50C9-9BD1-5289-95BE-C60B82E7530E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|ARM.ActiveCfg = Debug|ARM
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|ARM.Build.0 = Debug|ARM
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|ARM.Deploy.0 = Debug|ARM
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|ARM64.ActiveCfg = Debug|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|x64.ActiveCfg = Debug|x64
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|x64.Build.0 = Debug|x64
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|x64.Deploy.0 = Debug|x64
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|x86.ActiveCfg = Debug|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|x86.Build.0 = Debug|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Debug|x86.Deploy.0 = Debug|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|ARM.ActiveCfg = Release|ARM
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|ARM.Build.0 = Release|ARM
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|ARM.Deploy.0 = Release|ARM
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|ARM64.ActiveCfg = Release|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|x64.ActiveCfg = Release|x64
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|x64.Build.0 = Release|x64
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|x64.Deploy.0 = Release|x64
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|x86.ActiveCfg = Release|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|x86.Build.0 = Release|Win32
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}.Release|x86.Deploy.0 = Release|Win32
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|ARM.ActiveCfg = Debug|ARM
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|ARM.Build.0 = Debug|ARM
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|ARM64.Build.0 = Debug|ARM64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|x64.ActiveCfg = Debug|x64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|x64.Build.0 = Debug|x64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|x86.ActiveCfg = Debug|Win32
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Debug|x86.Build.0 = Debug|Win32
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|ARM.ActiveCfg = Release|ARM
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|ARM.Build.0 = Release|ARM
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|ARM64.ActiveCfg = Release|ARM64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|ARM64.Build.0 = Release|ARM64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|x64.ActiveCfg = Release|x64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|x64.Build.0 = Release|x64
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|x86.ActiveCfg = Release|Win32
+ {87FB50C9-9BD1-5289-95BE-C60B82E7530E}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {CB3C82E7-6013-4599-BEE6-88796AC4C4C3}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/HttpClient/cppwinrt/HttpClient.vcxproj b/Samples/HttpClient/cppwinrt/HttpClient.vcxproj
new file mode 100644
index 0000000000..188c40edc1
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/HttpClient.vcxproj
@@ -0,0 +1,362 @@
+
+
+
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), LICENSE))\SharedContent
+
+
+ true
+ {D2975110-E20D-5AC1-B6B1-4F544475362A}
+ HttpClient
+ SDKTemplate
+ en-US
+ 15.0
+ true
+ Windows Store
+ 10.0
+ 10.0.18362.0
+ $(WindowsTargetPlatformVersion)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);$(SharedContentDir)\cppwinrt
+ true
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ 4453;28204
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+
+
+
+
+ ..\shared\Scenario01_GetText.xaml
+ Code
+
+
+ ..\shared\Scenario02_GetStream.xaml
+ Code
+
+
+ ..\shared\Scenario03_GetList.xaml
+ Code
+
+
+ ..\shared\Scenario04_PostText.xaml
+ Code
+
+
+ ..\shared\Scenario05_PostStream.xaml
+ Code
+
+
+ ..\shared\Scenario06_PostMultipart.xaml
+ Code
+
+
+ ..\shared\Scenario07_PostStreamWithProgress.xaml
+ Code
+
+
+ ..\shared\Scenario08_PostCustomContent.xaml
+ Code
+
+
+ ..\shared\Scenario09_GetCookie.xaml
+ Code
+
+
+ ..\shared\Scenario10_SetCookie.xaml
+ Code
+
+
+ ..\shared\Scenario11_DeleteCookie.xaml
+ Code
+
+
+ ..\shared\Scenario12_DisableCookies.xaml
+ Code
+
+
+ ..\shared\Scenario13_RetryFilter.xaml
+ Code
+
+
+ ..\shared\Scenario14_MeteredConnectionFilter.xaml
+ Code
+
+
+ ..\shared\Scenario15_ServerCertificateValidation.xaml
+ Code
+
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+ Styles\Styles.xaml
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+ Helpers.h
+
+
+ HttpJsonContent.h
+
+
+ PlugInFilter.h
+
+
+ SampleConfiguration.h
+
+
+ Create
+ pch.h
+
+
+ Project.idl
+
+
+ ..\shared\Scenario01_GetText.xaml
+ Code
+
+
+ ..\shared\Scenario02_GetStream.xaml
+ Code
+
+
+ ..\shared\Scenario03_GetList.xaml
+ Code
+
+
+ ..\shared\Scenario04_PostText.xaml
+ Code
+
+
+ ..\shared\Scenario05_PostStream.xaml
+ Code
+
+
+ ..\shared\Scenario06_PostMultipart.xaml
+ Code
+
+
+ ..\shared\Scenario07_PostStreamWithProgress.xaml
+ Code
+
+
+ ..\shared\Scenario08_PostCustomContent.xaml
+ Code
+
+
+ ..\shared\Scenario09_GetCookie.xaml
+ Code
+
+
+ ..\shared\Scenario10_SetCookie.xaml
+ Code
+
+
+ ..\shared\Scenario11_DeleteCookie.xaml
+ Code
+
+
+ ..\shared\Scenario12_DisableCookies.xaml
+ Code
+
+
+ ..\shared\Scenario13_RetryFilter.xaml
+ Code
+
+
+ ..\shared\Scenario14_MeteredConnectionFilter.xaml
+ Code
+
+
+ ..\shared\Scenario15_ServerCertificateValidation.xaml
+ Code
+
+
+ SlowInputStream.h
+
+
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+ {b31fb521-eba9-5a64-93d7-4675dae9845b}
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/cppwinrt/HttpClient.vcxproj.filters b/Samples/HttpClient/cppwinrt/HttpClient.vcxproj.filters
new file mode 100644
index 0000000000..8e946c48f8
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/HttpClient.vcxproj.filters
@@ -0,0 +1,104 @@
+
+
+
+
+ 4416d50a-7676-4d0a-9b2c-91ff70c6047f
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/cppwinrt/HttpJsonContent.cpp b/Samples/HttpClient/cppwinrt/HttpJsonContent.cpp
new file mode 100644
index 0000000000..30cdfef3ed
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/HttpJsonContent.cpp
@@ -0,0 +1,110 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "HttpJsonContent.h"
+#include "HttpJsonContent.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Data::Json;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Security::Cryptography;
+using namespace winrt::Windows::Storage::Streams;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Headers;
+
+namespace winrt::SDKTemplate::implementation
+{
+ HttpJsonContent::HttpJsonContent(IJsonValue const& jsonValue) : m_jsonValue(jsonValue)
+ {
+ if (jsonValue == nullptr)
+ {
+ throw hresult_invalid_argument(L"jsonValue");
+ }
+
+ HttpMediaTypeHeaderValue headerValue(L"application/json");
+ headerValue.CharSet(L"UTF-8");
+ m_headers.ContentType(headerValue);
+ }
+
+ IAsyncOperationWithProgress HttpJsonContent::BufferAllAsync()
+ {
+ auto progress = co_await get_progress_token();
+ uint64_t length = GetLength();
+
+ // Report progress.
+ progress(length);
+
+ // Just return the size in bytes.
+ co_return length;
+ }
+
+ IAsyncOperationWithProgress HttpJsonContent::ReadAsBufferAsync()
+ {
+ co_return ToBuffer();
+ }
+
+ IAsyncOperationWithProgress HttpJsonContent::ReadAsInputStreamAsync()
+ {
+ auto lifetime = get_strong();
+ auto progress = co_await get_progress_token();
+
+ InMemoryRandomAccessStream randomAccessStream;
+ co_await randomAccessStream.WriteAsync(ToBuffer());
+
+ // Report progress.
+ progress(randomAccessStream.Size());
+
+ co_return randomAccessStream.GetInputStreamAt(0);
+ }
+
+ IAsyncOperationWithProgress HttpJsonContent::ReadAsStringAsync()
+ {
+ auto lifetime = get_strong();
+ auto progress = co_await get_progress_token();
+
+ hstring jsonString = m_jsonValue.Stringify();
+
+ // Report progress (length of string)
+ progress(jsonString.size());
+
+ co_return jsonString;
+ }
+
+ bool HttpJsonContent::TryComputeLength(uint64_t& length)
+ {
+ length = GetLength();
+ return true;
+ }
+
+ IAsyncOperationWithProgress HttpJsonContent::WriteToStreamAsync(IOutputStream outputStream)
+ {
+ auto lifetime = get_strong();
+ auto progress = co_await get_progress_token();
+
+ auto bytesStored = co_await outputStream.WriteAsync(ToBuffer());
+
+ // Report progress.
+ progress(bytesStored);
+
+ co_return bytesStored;
+ }
+
+ uint64_t HttpJsonContent::GetLength()
+ {
+ return ToBuffer().Length();
+ }
+
+ IBuffer HttpJsonContent::ToBuffer()
+ {
+ return CryptographicBuffer::ConvertStringToBinary(m_jsonValue.Stringify(), BinaryStringEncoding::Utf8);
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/HttpJsonContent.h b/Samples/HttpClient/cppwinrt/HttpJsonContent.h
new file mode 100644
index 0000000000..b14d3e10bb
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/HttpJsonContent.h
@@ -0,0 +1,42 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "HttpJsonContent.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct HttpJsonContent : HttpJsonContentT
+ {
+ HttpJsonContent(Windows::Data::Json::IJsonValue const& jsonValue);
+ Windows::Web::Http::Headers::HttpContentHeaderCollection Headers() { return m_headers; }
+ Windows::Foundation::IAsyncOperationWithProgress BufferAllAsync();
+ Windows::Foundation::IAsyncOperationWithProgress ReadAsBufferAsync();
+ Windows::Foundation::IAsyncOperationWithProgress ReadAsInputStreamAsync();
+ Windows::Foundation::IAsyncOperationWithProgress ReadAsStringAsync();
+ bool TryComputeLength(uint64_t& length);
+ Windows::Foundation::IAsyncOperationWithProgress WriteToStreamAsync(Windows::Storage::Streams::IOutputStream outputStream);
+ void Close() {}
+
+ private:
+ Windows::Data::Json::IJsonValue const m_jsonValue;
+ Windows::Web::Http::Headers::HttpContentHeaderCollection const m_headers;
+
+ Windows::Storage::Streams::IBuffer ToBuffer();
+ uint64_t GetLength();
+ };
+}
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct HttpJsonContent : HttpJsonContentT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Package.appxmanifest b/Samples/HttpClient/cppwinrt/Package.appxmanifest
new file mode 100644
index 0000000000..dec067fc70
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Package.appxmanifest
@@ -0,0 +1,43 @@
+
+
+
+
+
+ HttpClient C++/WinRT Sample
+ Microsoft Corporation
+ Assets\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/HttpClient/cppwinrt/PlugInFilter.cpp b/Samples/HttpClient/cppwinrt/PlugInFilter.cpp
new file mode 100644
index 0000000000..c013f01575
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/PlugInFilter.cpp
@@ -0,0 +1,57 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "PlugInFilter.h"
+#include "PlugInFilter.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ PlugInFilter::PlugInFilter(IHttpFilter const& innerFilter) : m_innerFilter(innerFilter)
+ {
+ if (innerFilter == nullptr)
+ {
+ throw hresult_invalid_argument(L"innerFilter cannot be null.");
+ }
+ }
+
+ IAsyncOperationWithProgress PlugInFilter::SendRequestAsync(HttpRequestMessage request)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+ auto progress = co_await get_progress_token();
+
+ request.Headers().Append(L"Custom-Header", L"CustomRequestValue");
+
+ IAsyncOperationWithProgress operation = m_innerFilter.SendRequestAsync(request);
+ operation.Progress([progress](auto&&, auto&& data) mutable
+ {
+ progress(data);
+ });
+ HttpResponseMessage response = co_await Helpers::AddCancellation(operation, cancellation);
+
+ response.Headers().Append(L"Custom-Header", L"CustomResponseValue");
+ co_return response;
+ }
+
+ void PlugInFilter::Close()
+ {
+ m_innerFilter.Close();
+ }
+}
+
+
diff --git a/Samples/HttpClient/cppwinrt/PlugInFilter.h b/Samples/HttpClient/cppwinrt/PlugInFilter.h
new file mode 100644
index 0000000000..ee7c16d557
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/PlugInFilter.h
@@ -0,0 +1,34 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "PlugInFilter.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct PlugInFilter : PlugInFilterT
+ {
+ PlugInFilter(Windows::Web::Http::Filters::IHttpFilter const& innerFilter);
+ Windows::Foundation::IAsyncOperationWithProgress
+ SendRequestAsync(Windows::Web::Http::HttpRequestMessage request);
+ void Close();
+
+ private:
+ Windows::Web::Http::Filters::IHttpFilter m_innerFilter;
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct PlugInFilter : PlugInFilterT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Project.idl b/Samples/HttpClient/cppwinrt/Project.idl
new file mode 100644
index 0000000000..7c9a0d1707
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Project.idl
@@ -0,0 +1,118 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+namespace SDKTemplate
+{
+ [default_interface]
+ runtimeclass Scenario01_GetText : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario01_GetText();
+ }
+
+ [default_interface]
+ runtimeclass Scenario02_GetStream : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario02_GetStream();
+ }
+
+ [default_interface]
+ runtimeclass Scenario03_GetList : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario03_GetList();
+ }
+
+ [default_interface]
+ runtimeclass Scenario04_PostText : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario04_PostText();
+ }
+
+ [default_interface]
+ runtimeclass Scenario05_PostStream : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario05_PostStream();
+ }
+
+ [default_interface]
+ runtimeclass Scenario06_PostMultipart : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario06_PostMultipart();
+ }
+
+ [default_interface]
+ runtimeclass Scenario07_PostStreamWithProgress : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario07_PostStreamWithProgress();
+ }
+
+ [default_interface]
+ runtimeclass Scenario08_PostCustomContent : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario08_PostCustomContent();
+ }
+
+ [default_interface]
+ runtimeclass Scenario09_GetCookie : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario09_GetCookie();
+ }
+
+ [default_interface]
+ runtimeclass Scenario10_SetCookie : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario10_SetCookie();
+ }
+
+ [default_interface]
+ runtimeclass Scenario11_DeleteCookie : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario11_DeleteCookie();
+ }
+
+ [default_interface]
+ runtimeclass Scenario12_DisableCookies : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario12_DisableCookies();
+ }
+
+ [default_interface]
+ runtimeclass Scenario13_RetryFilter : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario13_RetryFilter();
+ }
+
+ [default_interface]
+ runtimeclass Scenario14_MeteredConnectionFilter : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario14_MeteredConnectionFilter();
+ }
+
+ [default_interface]
+ runtimeclass Scenario15_ServerCertificateValidation : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario15_ServerCertificateValidation();
+ }
+
+ runtimeclass PlugInFilter : [default] Windows.Web.Http.Filters.IHttpFilter
+ {
+ PlugInFilter(Windows.Web.Http.Filters.IHttpFilter innerFilter);
+ }
+
+ runtimeclass SlowInputStream : [default] Windows.Storage.Streams.IInputStream
+ {
+ SlowInputStream(UInt32 length);
+ }
+
+ runtimeclass HttpJsonContent : [default] Windows.Web.Http.IHttpContent
+ {
+ HttpJsonContent(Windows.Data.Json.IJsonValue jsonValue);
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/SampleConfiguration.cpp b/Samples/HttpClient/cppwinrt/SampleConfiguration.cpp
new file mode 100644
index 0000000000..e87bacebfa
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/SampleConfiguration.cpp
@@ -0,0 +1,122 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include
+#include "MainPage.h"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::SDKTemplate;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+//using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::Web;
+using namespace winrt::Windows::Web::Http;
+//using namespace winrt::Windows::Web::Http::Filters;
+//using namespace winrt::Windows::Web::Http::Headers;
+
+hstring implementation::MainPage::FEATURE_NAME()
+{
+ return L"HttpClient C++/WinRT Sample";
+}
+
+IVector implementation::MainPage::scenariosInner = winrt::single_threaded_observable_vector(
+{
+ Scenario{ L"GET Text With Cache Control", xaml_typename() },
+ Scenario{ L"GET Stream", xaml_typename() },
+ Scenario{ L"GET List", xaml_typename() },
+ Scenario{ L"POST Text", xaml_typename() },
+ Scenario{ L"POST Stream", xaml_typename() },
+ Scenario{ L"POST Multipart", xaml_typename() },
+ Scenario{ L"POST Stream With Progress", xaml_typename() },
+ Scenario{ L"POST Custom Content", xaml_typename() },
+ Scenario{ L"Get Cookies", xaml_typename() },
+ Scenario{ L"Set Cookie", xaml_typename() },
+ Scenario{ L"Delete Cookie", xaml_typename() },
+ Scenario{ L"Disable Cookies", xaml_typename() },
+ Scenario{ L"Retry Filter", xaml_typename() },
+ Scenario{ L"Metered Connection Filter", xaml_typename() },
+ Scenario{ L"Server Certificate Validation", xaml_typename() },
+});
+
+hstring winrt::to_hstring(WebErrorStatus value)
+{
+ switch (value)
+ {
+ case WebErrorStatus::Unknown: return L"Unknown";
+ case WebErrorStatus::CertificateCommonNameIsIncorrect: return L"CertificateCommonNameIsIncorrect";
+ case WebErrorStatus::CertificateExpired: return L"CertificateExpired";
+ case WebErrorStatus::CertificateContainsErrors: return L"CertificateContainsErrors";
+ case WebErrorStatus::CertificateRevoked: return L"CertificateRevoked";
+ case WebErrorStatus::CertificateIsInvalid: return L"CertificateIsInvalid";
+ case WebErrorStatus::ServerUnreachable: return L"ServerUnreachable";
+ case WebErrorStatus::Timeout: return L"Timeout";
+ case WebErrorStatus::ErrorHttpInvalidServerResponse: return L"ErrorHttpInvalidServerResponse";
+ case WebErrorStatus::ConnectionAborted: return L"ConnectionAborted";
+ case WebErrorStatus::ConnectionReset: return L"ConnectionReset";
+ case WebErrorStatus::Disconnected: return L"Disconnected";
+ case WebErrorStatus::HttpToHttpsOnRedirection: return L"HttpToHttpsOnRedirection";
+ case WebErrorStatus::HttpsToHttpOnRedirection: return L"HttpsToHttpOnRedirection";
+ case WebErrorStatus::CannotConnect: return L"CannotConnect";
+ case WebErrorStatus::HostNameNotResolved: return L"HostNameNotResolved";
+ case WebErrorStatus::OperationCanceled: return L"OperationCanceled";
+ case WebErrorStatus::RedirectFailed: return L"RedirectFailed";
+ case WebErrorStatus::UnexpectedStatusCode: return L"UnexpectedStatusCode";
+ case WebErrorStatus::UnexpectedRedirection: return L"UnexpectedRedirection";
+ case WebErrorStatus::UnexpectedClientError: return L"UnexpectedClientError";
+ case WebErrorStatus::UnexpectedServerError: return L"UnexpectedServerError";
+ case WebErrorStatus::InsufficientRangeSupport: return L"InsufficientRangeSupport";
+ case WebErrorStatus::MissingContentLengthSupport: return L"MissingContentLengthSupport";
+ }
+ return to_hstring(static_cast(value));
+}
+
+hstring winrt::to_hstring(HttpResponseMessageSource value)
+{
+ switch (value)
+ {
+ case HttpResponseMessageSource::None: return L"None";
+ case HttpResponseMessageSource::Cache: return L"Cache";
+ case HttpResponseMessageSource::Network: return L"Network";
+ }
+ return to_hstring(static_cast(value));
+}
+
+hstring winrt::to_hstring(HttpVersion value)
+{
+ switch (value)
+ {
+ case HttpVersion::None: return L"None";
+ case HttpVersion::Http10: return L"HTTP 1.0";
+ case HttpVersion::Http11: return L"HTTP 1.1";
+ case HttpVersion::Http20: return L"HTTP 2.0";
+ }
+ return to_hstring(static_cast(value));
+}
+
+hstring winrt::to_hstring(HttpProgressStage value)
+{
+ switch (value)
+ {
+ case HttpProgressStage::None: return L"None";
+ case HttpProgressStage::DetectingProxy: return L"Detecting proxy";
+ case HttpProgressStage::ResolvingName: return L"Resolving name";
+ case HttpProgressStage::ConnectingToServer: return L"Connecting to server";
+ case HttpProgressStage::NegotiatingSsl: return L"Negotiating SSL";
+ case HttpProgressStage::SendingHeaders: return L"Sending headers";
+ case HttpProgressStage::SendingContent: return L"Sending content";
+ case HttpProgressStage::WaitingForResponse: return L"Waiting for response";
+ case HttpProgressStage::ReceivingHeaders: return L"Receiving headers";
+ case HttpProgressStage::ReceivingContent: return L"Receiving content";
+ }
+ return to_hstring(static_cast(value));
+}
diff --git a/Samples/HttpClient/cppwinrt/SampleConfiguration.h b/Samples/HttpClient/cppwinrt/SampleConfiguration.h
new file mode 100644
index 0000000000..a3eb46961a
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/SampleConfiguration.h
@@ -0,0 +1,25 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace winrt
+{
+ hstring to_hstring(Windows::Web::WebErrorStatus value);
+ hstring to_hstring(Windows::Web::Http::HttpResponseMessageSource value);
+ hstring to_hstring(Windows::Web::Http::HttpVersion value);
+ hstring to_hstring(Windows::Web::Http::HttpProgressStage value);
+}
+
+namespace winrt::SDKTemplate
+{
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario01_GetText.cpp b/Samples/HttpClient/cppwinrt/Scenario01_GetText.cpp
new file mode 100644
index 0000000000..38555bd291
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario01_GetText.cpp
@@ -0,0 +1,180 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario01_GetText.h"
+#include "Scenario01_GetText.g.cpp"
+#include "SampleConfiguration.h"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Security::Cryptography::Certificates;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario01_GetText::Scenario01_GetText()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario01_GetText::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ // In this scenario we just create an HttpClient instance with default settings. I.e. no custom filters.
+ // For examples on how to use custom filters see other scenarios.
+ filter = HttpBaseProtocolFilter();
+
+ // Setting the starting state of the toggle based on the default HTTP version in the OS
+ if (filter.MaxVersion() >= HttpVersion::Http20)
+ {
+ MaxHttpVersionToggle().IsOn(true);
+ }
+ else
+ {
+ MaxHttpVersionToggle().IsOn(false);
+ }
+
+ httpClient = HttpClient(filter);
+ isFilterUsed = false;
+ }
+
+ void Scenario01_GetText::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ filter.Close();
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario01_GetText::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ if (ReadDefaultRadio().IsChecked().Value())
+ {
+ filter.CacheControl().ReadBehavior(HttpCacheReadBehavior::Default);
+ }
+ else if (ReadMostRecentRadio().IsChecked().Value())
+ {
+ filter.CacheControl().ReadBehavior(HttpCacheReadBehavior::MostRecent);
+ }
+ else if (ReadOnlyFromCacheRadio().IsChecked().Value())
+ {
+ filter.CacheControl().ReadBehavior(HttpCacheReadBehavior::OnlyFromCache);
+ }
+ else if (ReadNoCacheRadio().IsChecked().Value())
+ {
+ filter.CacheControl().ReadBehavior(HttpCacheReadBehavior::NoCache);
+ }
+
+ if (WriteDefaultRadio().IsChecked().Value())
+ {
+ filter.CacheControl().WriteBehavior(HttpCacheWriteBehavior::Default);
+ }
+ else if (WriteNoCacheRadio().IsChecked().Value())
+ {
+ filter.CacheControl().WriteBehavior(HttpCacheWriteBehavior::NoCache);
+ }
+
+ // ---------------------------------------------------------------------------
+ // WARNING: Only test applications should ignore SSL errors.
+ // In real applications, ignoring server certificate errors can lead to MITM
+ // attacks (while the connection is secure, the server is not authenticated).
+ //
+ // The SetupServer script included with this sample creates a server certificate that is self-signed
+ // and issued to fabrikam.com, and hence we need to ignore these errors here.
+ // ---------------------------------------------------------------------------
+ filter.IgnorableServerCertificateErrors().ReplaceAll({ ChainValidationResult::Untrusted, ChainValidationResult::InvalidName });
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario01_GetText::CancelableRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ isFilterUsed = true;
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TryGetAsync(resourceUri), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(
+ L"Completed. Response came from " + to_hstring(result.ResponseMessage().Source()) + L". HTTP version used: " + to_hstring(result.ResponseMessage().Version()) + L".",
+ NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+
+ void Scenario01_GetText::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+
+ void Scenario01_GetText::MaxHttpVersionToggle_Toggled(IInspectable const&, RoutedEventArgs const&)
+ {
+ HttpVersion httpVersion = HttpVersion::Http11;
+ if (MaxHttpVersionToggle().IsOn())
+ {
+ httpVersion = HttpVersion::Http20;
+ }
+
+ // In general, for best memory utilization, HttpBaseProtocolFilter and HttpClient objects should be reused for multiple requests.
+ // However, if the user has already used the filter object to send at least one request, the HTTP version of the filter cannot be changed.
+ // Hence, we need to create new client and filter objects.
+ if (isFilterUsed)
+ {
+ filter.Close();
+ httpClient.Close();
+ filter = HttpBaseProtocolFilter();
+ httpClient = HttpClient(filter);
+ isFilterUsed = false;
+ }
+ filter.MaxVersion(httpVersion);
+ }
+
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario01_GetText.h b/Samples/HttpClient/cppwinrt/Scenario01_GetText.h
new file mode 100644
index 0000000000..951a3ca07a
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario01_GetText.h
@@ -0,0 +1,47 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario01_GetText.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario01_GetText : Scenario01_GetTextT
+ {
+ Scenario01_GetText();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void MaxHttpVersionToggle_Toggled(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::Filters::HttpBaseProtocolFilter filter{ nullptr };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+ bool isFilterUsed = false;
+
+ private:
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario01_GetText : Scenario01_GetTextT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario02_GetStream.cpp b/Samples/HttpClient/cppwinrt/Scenario02_GetStream.cpp
new file mode 100644
index 0000000000..473a043fb9
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario02_GetStream.cpp
@@ -0,0 +1,123 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario02_GetStream.h"
+#include "Scenario02_GetStream.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Security::Cryptography;
+using namespace winrt::Windows::Storage::Streams;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario02_GetStream::Scenario02_GetStream()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario02_GetStream::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario02_GetStream::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario02_GetStream::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ HttpRequestMessage request(HttpMethod::Get(), resourceUri);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(request);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario02_GetStream::CancelableRequestAsync(HttpRequestMessage request)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ // Do not buffer the response.
+ HttpRequestResult result = co_await Helpers::AddCancellation(
+ httpClient.TrySendRequestAsync(request, HttpCompletionOption::ResponseHeadersRead), cancellation);
+
+ if (result.Succeeded())
+ {
+ OutputField().Text(OutputField().Text() + Helpers::SerializeHeaders(result.ResponseMessage()));
+
+ std::wostringstream responseBody;
+ IInputStream responseStream = co_await Helpers::AddCancellation(result.ResponseMessage().Content().ReadAsInputStreamAsync(), cancellation);
+ Buffer readBuffer(1000);
+ IBuffer resultBuffer;
+ do
+ {
+ resultBuffer = co_await Helpers::AddCancellation(responseStream.ReadAsync(readBuffer, readBuffer.Capacity(), InputStreamOptions::Partial), cancellation);
+
+ responseBody << L"Bytes read from stream: " << resultBuffer.Length() << L"\n";
+
+ // Use the buffer contents for something. We can't safely display it as a string though, since encodings
+ // like UTF-8 and UTF-16 have a variable number of bytes per character and so the last bytes in the buffer
+ // may not contain a whole character. Instead, we'll convert the bytes to hex and display the result.
+ hstring resultText = CryptographicBuffer::EncodeToHexString(resultBuffer);
+ responseBody << std::wstring_view(resultText) << L"\n";
+ } while (resultBuffer.Length() > 0);
+ responseStream.Close();
+
+ OutputField().Text(OutputField().Text() + responseBody.str());
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario02_GetStream::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario02_GetStream.h b/Samples/HttpClient/cppwinrt/Scenario02_GetStream.h
new file mode 100644
index 0000000000..b1c11cc601
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario02_GetStream.h
@@ -0,0 +1,43 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario02_GetStream.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario02_GetStream : Scenario02_GetStreamT
+ {
+ Scenario02_GetStream();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Web::Http::HttpRequestMessage request);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario02_GetStream : Scenario02_GetStreamT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario03_GetList.cpp b/Samples/HttpClient/cppwinrt/Scenario03_GetList.cpp
new file mode 100644
index 0000000000..73c3ad1a7c
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario03_GetList.cpp
@@ -0,0 +1,121 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario03_GetList.h"
+#include "Scenario03_GetList.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Data::Xml::Dom;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario03_GetList::Scenario03_GetList()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario03_GetList::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario03_GetList::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario03_GetList::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+ catch (hresult_error const& ex)
+ {
+ rootPage.NotifyUser(L"Error: " + ex.message() , NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario03_GetList::CancelableRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TryGetAsync(resourceUri), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+ hstring contentString = co_await Helpers::AddCancellation(result.ResponseMessage().Content().ReadAsStringAsync(), cancellation);
+
+ XmlDocument xmlDocument;
+ try
+ {
+ xmlDocument.LoadXml(contentString);
+ }
+ catch (hresult_error const&)
+ {
+ // Invalid XML.
+ }
+
+ // Create a collection to bind to the view.
+ std::vector items;
+ for (IXmlNode node : xmlDocument.GetElementsByTagName(L"item"))
+ {
+ items.push_back(node.as().GetAttribute(L"name"));
+ }
+ OutputList().ItemsSource(single_threaded_observable_vector(std::move(items)));
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario03_GetList::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario03_GetList.h b/Samples/HttpClient/cppwinrt/Scenario03_GetList.h
new file mode 100644
index 0000000000..08b5d7c801
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario03_GetList.h
@@ -0,0 +1,43 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario03_GetList.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario03_GetList : Scenario03_GetListT
+ {
+ Scenario03_GetList();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario03_GetList : Scenario03_GetListT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario04_PostText.cpp b/Samples/HttpClient/cppwinrt/Scenario04_PostText.cpp
new file mode 100644
index 0000000000..67ea8c406c
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario04_PostText.cpp
@@ -0,0 +1,98 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario04_PostText.h"
+#include "Scenario04_PostText.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario04_PostText::Scenario04_PostText()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario04_PostText::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario04_PostText::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario04_PostText::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario04_PostText::CancelableRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(
+ httpClient.TryPostAsync(resourceUri, HttpStringContent(RequestBodyField().Text())), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario04_PostText::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario04_PostText.h b/Samples/HttpClient/cppwinrt/Scenario04_PostText.h
new file mode 100644
index 0000000000..1381a9c403
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario04_PostText.h
@@ -0,0 +1,43 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario04_PostText.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario04_PostText : Scenario04_PostTextT
+ {
+ Scenario04_PostText();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario04_PostText : Scenario04_PostTextT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario05_PostStream.cpp b/Samples/HttpClient/cppwinrt/Scenario05_PostStream.cpp
new file mode 100644
index 0000000000..b13504982a
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario05_PostStream.cpp
@@ -0,0 +1,128 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario05_PostStream.h"
+#include "Scenario05_PostStream.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Storage::Streams;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace
+{
+ IAsyncOperation GenerateSampleStreamAsync(int contentLength)
+ {
+ auto cancellation = co_await get_cancellation_token();
+
+ Buffer buffer(contentLength);
+ memset(buffer.data(), '@', contentLength);
+
+ InMemoryRandomAccessStream stream;
+ co_await SDKTemplate::Helpers::AddCancellation(stream.WriteAsync(buffer), cancellation);
+
+ // Rewind the stream.
+ stream.Seek(0);
+
+ co_return stream;
+ }
+}
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario05_PostStream::Scenario05_PostStream()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario05_PostStream::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario05_PostStream::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario05_PostStream::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ static constexpr int contentLength = 1000;
+ IRandomAccessStream stream = co_await GenerateSampleStreamAsync(contentLength);
+
+ // If the stream does not implement the IRandomAccessStream interface,
+ // chunked transfer encoding is used during the request.
+ HttpStreamContent streamContent(stream);
+
+ HttpRequestMessage request(HttpMethod::Post(), resourceUri);
+ request.Content(streamContent);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(request);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario05_PostStream::CancelableRequestAsync(HttpRequestMessage request)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ // Do an asynchronous POST.
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TrySendRequestAsync(request), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario05_PostStream::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario05_PostStream.h b/Samples/HttpClient/cppwinrt/Scenario05_PostStream.h
new file mode 100644
index 0000000000..c24703db04
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario05_PostStream.h
@@ -0,0 +1,43 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario05_PostStream.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario05_PostStream : Scenario05_PostStreamT
+ {
+ Scenario05_PostStream();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Web::Http::HttpRequestMessage request);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario05_PostStream : Scenario05_PostStreamT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario06_PostMultipart.cpp b/Samples/HttpClient/cppwinrt/Scenario06_PostMultipart.cpp
new file mode 100644
index 0000000000..a8941a5052
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario06_PostMultipart.cpp
@@ -0,0 +1,101 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario06_PostMultipart.h"
+#include "Scenario06_PostMultipart.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario06_PostMultipart::Scenario06_PostMultipart()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario06_PostMultipart::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario06_PostMultipart::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario06_PostMultipart::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ HttpMultipartFormDataContent form;
+ form.Add(HttpStringContent(RequestBodyField().Text()), L"data");
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri, form);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario06_PostMultipart::CancelableRequestAsync(Uri resourceUri, HttpMultipartFormDataContent form)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(
+ httpClient.TryPostAsync(resourceUri, form), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario06_PostMultipart::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario06_PostMultipart.h b/Samples/HttpClient/cppwinrt/Scenario06_PostMultipart.h
new file mode 100644
index 0000000000..10d73b0982
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario06_PostMultipart.h
@@ -0,0 +1,45 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario06_PostMultipart.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario06_PostMultipart : Scenario06_PostMultipartT
+ {
+ Scenario06_PostMultipart();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(
+ Windows::Foundation::Uri resourceUri,
+ Windows::Web::Http::HttpMultipartFormDataContent form);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario06_PostMultipart : Scenario06_PostMultipartT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario07_PostStreamWithProgress.cpp b/Samples/HttpClient/cppwinrt/Scenario07_PostStreamWithProgress.cpp
new file mode 100644
index 0000000000..fc20c1e6f2
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario07_PostStreamWithProgress.cpp
@@ -0,0 +1,195 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario07_PostStreamWithProgress.h"
+#include "Scenario07_PostStreamWithProgress.g.cpp"
+#include "SampleConfiguration.h"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario07_PostStreamWithProgress::Scenario07_PostStreamWithProgress()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario07_PostStreamWithProgress::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario07_PostStreamWithProgress::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ void Scenario07_PostStreamWithProgress::UpdateAddressField()
+ {
+ // Tell the server we want a transfer-encoding chunked response.
+ hstring queryString{};
+ if (ChunkedResponseToggle().IsOn())
+ {
+ queryString = L"?chunkedResponse=1";
+ }
+
+ Helpers::ReplaceQueryString(AddressField(), queryString);
+ }
+
+ void Scenario07_PostStreamWithProgress::ChunkedResponseToggle_Toggled(IInspectable const&, RoutedEventArgs const&)
+ {
+ UpdateAddressField();
+ }
+
+ fire_and_forget Scenario07_PostStreamWithProgress::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), nullptr);
+ ResetFields();
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ static constexpr uint32_t streamLength = 100000;
+ HttpStreamContent streamContent{ SlowInputStream(streamLength) };
+
+ // If stream length is unknown, the request is chunked transfer encoded.
+ if (!ChunkedRequestToggle().IsOn())
+ {
+ streamContent.Headers().ContentLength(streamLength);
+ }
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri, streamContent);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario07_PostStreamWithProgress::CancelableRequestAsync(Uri resourceUri, IHttpContent content)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ IAsyncOperationWithProgress operation = httpClient.TryPostAsync(resourceUri, content);
+ operation.Progress({ get_weak(), &Scenario07_PostStreamWithProgress::ProgressHandler });
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(operation, cancellation);
+
+ if (result.Succeeded())
+ {
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario07_PostStreamWithProgress::ResetFields()
+ {
+ StageField().Text(L"");
+ RetriesField().Text(L"0");
+ BytesSentField().Text(L"0");
+ TotalBytesToSendField().Text(L"0");
+ BytesReceivedField().Text(L"0");
+ TotalBytesToReceiveField().Text(L"0");
+ RequestProgressBar().Value(0);
+ }
+
+ fire_and_forget Scenario07_PostStreamWithProgress::ProgressHandler(
+ IAsyncOperationWithProgress const&,
+ HttpProgress progress)
+ {
+ auto lifetime = get_strong();
+
+ co_await resume_foreground(Dispatcher());
+
+ StageField().Text(to_hstring(progress.Stage));
+ RetriesField().Text(to_hstring(progress.Retries));
+ BytesSentField().Text(to_hstring(progress.BytesSent));
+ BytesReceivedField().Text(to_hstring(progress.BytesReceived));
+
+ uint64_t totalBytesToSend = 0;
+ if (progress.TotalBytesToSend != nullptr)
+ {
+ totalBytesToSend = progress.TotalBytesToSend.Value();
+ TotalBytesToSendField().Text(to_hstring(totalBytesToSend));
+ }
+ else
+ {
+ TotalBytesToSendField().Text(L"unknown");
+ }
+
+ uint64_t totalBytesToReceive = 0;
+ if (progress.TotalBytesToReceive != nullptr)
+ {
+ totalBytesToReceive = progress.TotalBytesToReceive.Value();
+ TotalBytesToReceiveField().Text(to_hstring(totalBytesToReceive));
+ }
+ else
+ {
+ TotalBytesToReceiveField().Text(L"unknown");
+ }
+
+ double requestProgress = 0.0;
+ if (progress.Stage == HttpProgressStage::SendingContent && totalBytesToSend > 0)
+ {
+ requestProgress = progress.BytesSent * 50.0 / totalBytesToSend;
+ }
+ else if (progress.Stage == HttpProgressStage::ReceivingContent)
+ {
+ // Start with 50 percent, request content was already sent.
+ requestProgress += 50.0;
+
+ if (totalBytesToReceive > 0)
+ {
+ requestProgress += progress.BytesReceived * 50.0 / totalBytesToReceive;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ RequestProgressBar().Value(requestProgress);
+ }
+
+ void Scenario07_PostStreamWithProgress::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario07_PostStreamWithProgress.h b/Samples/HttpClient/cppwinrt/Scenario07_PostStreamWithProgress.h
new file mode 100644
index 0000000000..e8a22e8949
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario07_PostStreamWithProgress.h
@@ -0,0 +1,52 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario07_PostStreamWithProgress.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario07_PostStreamWithProgress : Scenario07_PostStreamWithProgressT
+ {
+ Scenario07_PostStreamWithProgress();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ void ChunkedResponseToggle_Toggled(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ void UpdateAddressField();
+ void ResetFields();
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(
+ Windows::Foundation::Uri resourceUri,
+ Windows::Web::Http::IHttpContent content);
+ fire_and_forget ProgressHandler(
+ Windows::Foundation::IAsyncOperationWithProgress const& sender,
+ Windows::Web::Http::HttpProgress progress);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario07_PostStreamWithProgress : Scenario07_PostStreamWithProgressT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario08_PostCustomContent.cpp b/Samples/HttpClient/cppwinrt/Scenario08_PostCustomContent.cpp
new file mode 100644
index 0000000000..f176cd1ac8
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario08_PostCustomContent.cpp
@@ -0,0 +1,101 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario08_PostCustomContent.h"
+#include "Scenario08_PostCustomContent.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Data::Json;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario08_PostCustomContent::Scenario08_PostCustomContent()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario08_PostCustomContent::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario08_PostCustomContent::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ fire_and_forget Scenario08_PostCustomContent::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ HttpJsonContent jsonContent(JsonValue::Parse(L"{\"score\": 100, \"enabled\": false}"));
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri, jsonContent);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario08_PostCustomContent::CancelableRequestAsync(Uri resourceUri, IHttpContent content)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(
+ httpClient.TryPostAsync(resourceUri, content), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario08_PostCustomContent::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario08_PostCustomContent.h b/Samples/HttpClient/cppwinrt/Scenario08_PostCustomContent.h
new file mode 100644
index 0000000000..cc44b343fc
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario08_PostCustomContent.h
@@ -0,0 +1,45 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario08_PostCustomContent.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario08_PostCustomContent : Scenario08_PostCustomContentT
+ {
+ Scenario08_PostCustomContent();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(
+ Windows::Foundation::Uri resourceUri,
+ Windows::Web::Http::IHttpContent content);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario08_PostCustomContent : Scenario08_PostCustomContentT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario09_GetCookie.cpp b/Samples/HttpClient/cppwinrt/Scenario09_GetCookie.cpp
new file mode 100644
index 0000000000..2174979ee6
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario09_GetCookie.cpp
@@ -0,0 +1,140 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario09_GetCookie.h"
+#include "Scenario09_GetCookie.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario09_GetCookie::Scenario09_GetCookie()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario09_GetCookie::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ httpClient = Helpers::CreateHttpClientWithCustomHeaders();
+ }
+
+ void Scenario09_GetCookie::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ void Scenario09_GetCookie::GetCookies_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+ try
+ {
+ HttpBaseProtocolFilter filter;
+ HttpCookieCollection cookieCollection = filter.CookieManager().GetCookies(resourceUri);
+
+ std::wostringstream result;
+
+ result << cookieCollection.Size() << L" cookies found.\n";
+
+ for (HttpCookie cookie : cookieCollection)
+ {
+ result
+ << L"--------------------\n"
+ << L"Name: " << std::wstring_view(cookie.Name()) << L"\n"
+ << L"Domain: " << std::wstring_view(cookie.Domain()) << L"\n"
+ << L"Path: " << std::wstring_view(cookie.Path()) << L"\n"
+ << L"Value: " << std::wstring_view(cookie.Value()) << L"\n";
+ if (auto expires = cookie.Expires())
+ {
+ result << L"Expires: " << std::wstring_view(Helpers::ToSimpleString(expires.Value())) << L"\n";
+ }
+ result
+ << L"Secure: " << cookie.Secure() << L"\n"
+ << L"HttpOnly: " << cookie.HttpOnly() << L"\n";
+ }
+ OutputField().Text(result.str());
+ }
+ catch (hresult_error const& ex)
+ {
+ rootPage.NotifyUser(L"Error: " + ex.message(), NotifyType::ErrorMessage);
+ }
+ }
+
+ fire_and_forget Scenario09_GetCookie::SendHttpGetButton_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(SendHttpGetButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(SendHttpGetButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario09_GetCookie::CancelableRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(
+ httpClient.TryGetAsync(resourceUri), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario09_GetCookie::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario09_GetCookie.h b/Samples/HttpClient/cppwinrt/Scenario09_GetCookie.h
new file mode 100644
index 0000000000..3787143c3a
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario09_GetCookie.h
@@ -0,0 +1,44 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario09_GetCookie.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario09_GetCookie : Scenario09_GetCookieT
+ {
+ Scenario09_GetCookie();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ void GetCookies_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ fire_and_forget SendHttpGetButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario09_GetCookie : Scenario09_GetCookieT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario10_SetCookie.cpp b/Samples/HttpClient/cppwinrt/Scenario10_SetCookie.cpp
new file mode 100644
index 0000000000..a598485307
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario10_SetCookie.cpp
@@ -0,0 +1,79 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario10_SetCookie.h"
+#include "Scenario10_SetCookie.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario10_SetCookie::Scenario10_SetCookie()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario10_SetCookie::SetCookie_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ hstring name = NameField().Text();
+ hstring domain = DomainField().Text();
+ hstring path = PathField().Text();
+
+ if (name.empty() || domain.empty() || path.empty())
+ {
+ rootPage.NotifyUser(L"Invalid name, domain, or path value.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ try
+ {
+ HttpCookie cookie(name, domain, path);
+ cookie.Value(ValueField().Text());
+
+ if (NullCheckBox().IsChecked().Value())
+ {
+ cookie.Expires(nullptr);
+ }
+ else
+ {
+ cookie.Expires(ExpiresDatePicker().Date() + ExpiresTimePicker().Time());
+ }
+
+ cookie.Secure(SecureToggle().IsOn());
+ cookie.HttpOnly(HttpOnlyToggle().IsOn());
+
+ HttpBaseProtocolFilter filter;
+ bool replaced = filter.CookieManager().SetCookie(cookie, false);
+
+ if (replaced)
+ {
+ rootPage.NotifyUser(L"Cookie replaced.", NotifyType::StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser(L"Cookie set.", NotifyType::StatusMessage);
+ }
+ }
+ catch (hresult_invalid_argument const& ex)
+ {
+ rootPage.NotifyUser(ex.message(), NotifyType::StatusMessage);
+ }
+ catch (hresult_error const& ex)
+ {
+ rootPage.NotifyUser(L"Error: " + ex.message(), NotifyType::ErrorMessage);
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario10_SetCookie.h b/Samples/HttpClient/cppwinrt/Scenario10_SetCookie.h
new file mode 100644
index 0000000000..1a228c496c
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario10_SetCookie.h
@@ -0,0 +1,35 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario10_SetCookie.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario10_SetCookie : Scenario10_SetCookieT
+ {
+ Scenario10_SetCookie();
+
+ void SetCookie_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario10_SetCookie : Scenario10_SetCookieT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario11_DeleteCookie.cpp b/Samples/HttpClient/cppwinrt/Scenario11_DeleteCookie.cpp
new file mode 100644
index 0000000000..18f9ac4fa9
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario11_DeleteCookie.cpp
@@ -0,0 +1,59 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario11_DeleteCookie.h"
+#include "Scenario11_DeleteCookie.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario11_DeleteCookie::Scenario11_DeleteCookie()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario11_DeleteCookie::DeleteCookie_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ hstring name = NameField().Text();
+ hstring domain = DomainField().Text();
+ hstring path = PathField().Text();
+
+ if (name.empty() || domain.empty() || path.empty())
+ {
+ rootPage.NotifyUser(L"Invalid name, domain, or path value.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ try
+ {
+ HttpCookie cookie(name, domain, path);
+
+ HttpBaseProtocolFilter filter;
+ filter.CookieManager().DeleteCookie(cookie);
+
+ rootPage.NotifyUser(L"Cookie deleted.", NotifyType::StatusMessage);
+ }
+ catch (hresult_invalid_argument const& ex)
+ {
+ rootPage.NotifyUser(ex.message(), NotifyType::StatusMessage);
+ }
+ catch (hresult_error const& ex)
+ {
+ rootPage.NotifyUser(L"Error: " + ex.message(), NotifyType::ErrorMessage);
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario11_DeleteCookie.h b/Samples/HttpClient/cppwinrt/Scenario11_DeleteCookie.h
new file mode 100644
index 0000000000..fb3f1e31f0
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario11_DeleteCookie.h
@@ -0,0 +1,35 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario11_DeleteCookie.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario11_DeleteCookie : Scenario11_DeleteCookieT
+ {
+ Scenario11_DeleteCookie();
+
+ void DeleteCookie_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario11_DeleteCookie : Scenario11_DeleteCookieT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario12_DisableCookies.cpp b/Samples/HttpClient/cppwinrt/Scenario12_DisableCookies.cpp
new file mode 100644
index 0000000000..6eab065fce
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario12_DisableCookies.cpp
@@ -0,0 +1,184 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario12_DisableCookies.h"
+#include "Scenario12_DisableCookies.g.cpp"
+#include "SampleConfiguration.h"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario12_DisableCookies::Scenario12_DisableCookies()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario12_DisableCookies::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ filter = HttpBaseProtocolFilter();
+ httpClient = HttpClient(filter);
+ }
+
+ void Scenario12_DisableCookies::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ filter.Close();
+ }
+
+ fire_and_forget Scenario12_DisableCookies::SendInitialGetButton_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(SendInitialGetButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableInitialRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(SendInitialGetButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario12_DisableCookies::CancelableInitialRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TryGetAsync(resourceUri), cancellation);
+
+ if (result.Succeeded())
+ {
+ std::wostringstream output;
+
+ HttpCookieCollection cookieCollection = filter.CookieManager().GetCookies(resourceUri);
+ output << cookieCollection.Size() << L" cookies found.\n";
+ for (HttpCookie cookie : cookieCollection)
+ {
+ output
+ << L"--------------------\n"
+ << L"Name: " << std::wstring_view(cookie.Name()) << L"\n"
+ << L"Domain: " << std::wstring_view(cookie.Domain()) << L"\n"
+ << L"Path: " << std::wstring_view(cookie.Path()) << L"\n"
+ << L"Value: " << std::wstring_view(cookie.Value()) << L"\n";
+ if (auto expires = cookie.Expires())
+ {
+ output << L"Expires: " << std::wstring_view(Helpers::ToSimpleString(expires.Value())) << L"\n";
+ }
+ output
+ << L"Secure: " << cookie.Secure() << L"\n"
+ << L"HttpOnly: " << cookie.HttpOnly() << L"\n";
+ }
+ OutputField().Text(output.str());
+
+ SendNextRequestButton().IsEnabled(true);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ fire_and_forget Scenario12_DisableCookies::SendNextRequestButton_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(SendNextRequestButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ if (CookieUsageBehaviorToggle().IsOn())
+ {
+ filter.CookieUsageBehavior(HttpCookieUsageBehavior::Default);
+ }
+ else
+ {
+ // Disable cookie handling - this will do two things: no cookies are attached to outgoing request, and
+ // cookies contained in incoming server responses are not added to the CookieManager of the HttpBaseProtocolFilter.
+ filter.CookieUsageBehavior(HttpCookieUsageBehavior::NoCookies);
+ }
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableNextRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(SendNextRequestButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario12_DisableCookies::CancelableNextRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TryGetAsync(resourceUri), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed. Response came from " +
+ to_hstring(result.ResponseMessage().Source()) + L".",
+ NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario12_DisableCookies::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario12_DisableCookies.h b/Samples/HttpClient/cppwinrt/Scenario12_DisableCookies.h
new file mode 100644
index 0000000000..2742d309b1
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario12_DisableCookies.h
@@ -0,0 +1,46 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario12_DisableCookies.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario12_DisableCookies : Scenario12_DisableCookiesT
+ {
+ Scenario12_DisableCookies();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget SendInitialGetButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ fire_and_forget SendNextRequestButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::Filters::HttpBaseProtocolFilter filter{ nullptr };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableInitialRequestAsync(Windows::Foundation::Uri resourceUri);
+ Windows::Foundation::IAsyncAction CancelableNextRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario12_DisableCookies : Scenario12_DisableCookiesT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario13_RetryFilter.cpp b/Samples/HttpClient/cppwinrt/Scenario13_RetryFilter.cpp
new file mode 100644
index 0000000000..28c12cb58f
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario13_RetryFilter.cpp
@@ -0,0 +1,123 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario13_RetryFilter.h"
+#include "Scenario13_RetryFilter.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::HttpFilters;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario13_RetryFilter::Scenario13_RetryFilter()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario13_RetryFilter::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ HttpBaseProtocolFilter baseProtocolFilter;
+ HttpRetryFilter retryFilter(baseProtocolFilter);
+ httpClient = HttpClient(retryFilter);
+ UpdateAddressField();
+ }
+
+ void Scenario13_RetryFilter::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ }
+
+ void Scenario13_RetryFilter::UpdateAddressField()
+ {
+ // Tell the server which type of Retry-After header we would like to receive.
+ hstring queryString;
+ if (RetryAfterSwitch().IsOn())
+ {
+ queryString = L"?retryAfter=deltaSeconds";
+ }
+ else
+ {
+ queryString = L"?retryAfter=httpDate";
+ }
+
+ Helpers::ReplaceQueryString(AddressField(), queryString);
+ }
+
+ void Scenario13_RetryFilter::RetryAfterSwitch_Toggled(IInspectable const&, RoutedEventArgs const&)
+ {
+ UpdateAddressField();
+ }
+
+ fire_and_forget Scenario13_RetryFilter::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario13_RetryFilter::CancelableRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TryGetAsync(resourceUri), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario13_RetryFilter::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario13_RetryFilter.h b/Samples/HttpClient/cppwinrt/Scenario13_RetryFilter.h
new file mode 100644
index 0000000000..223c0e5cc0
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario13_RetryFilter.h
@@ -0,0 +1,45 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario13_RetryFilter.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario13_RetryFilter : Scenario13_RetryFilterT
+ {
+ Scenario13_RetryFilter();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ void RetryAfterSwitch_Toggled(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ void UpdateAddressField();
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario13_RetryFilter : Scenario13_RetryFilterT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario14_MeteredConnectionFilter.cpp b/Samples/HttpClient/cppwinrt/Scenario14_MeteredConnectionFilter.cpp
new file mode 100644
index 0000000000..032aba9b88
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario14_MeteredConnectionFilter.cpp
@@ -0,0 +1,120 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario14_MeteredConnectionFilter.h"
+#include "Scenario14_MeteredConnectionFilter.g.cpp"
+#include "Helpers.h"
+
+using namespace winrt;
+using namespace winrt::HttpFilters;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario14_MeteredConnectionFilter::Scenario14_MeteredConnectionFilter()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario14_MeteredConnectionFilter::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ HttpBaseProtocolFilter baseProtocolFilter;
+ meteredConnectionFilter = HttpMeteredConnectionFilter(baseProtocolFilter);
+ httpClient = HttpClient(meteredConnectionFilter);
+ }
+
+ void Scenario14_MeteredConnectionFilter::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ meteredConnectionFilter.Close();
+ }
+
+ void Scenario14_MeteredConnectionFilter::OptInSwitch_Toggled(IInspectable const&, RoutedEventArgs const&)
+ {
+ meteredConnectionFilter.OptIn(OptInSwitch().IsOn());
+ }
+
+ fire_and_forget Scenario14_MeteredConnectionFilter::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), OutputField());
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(resourceUri);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario14_MeteredConnectionFilter::CancelableRequestAsync(Uri resourceUri)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestMessage request(HttpMethod::Get(), resourceUri);
+
+ MeteredConnectionPriority priority = MeteredConnectionPriority::Low;
+ if (MediumRadio().IsChecked().Value())
+ {
+ priority = MeteredConnectionPriority::Medium;
+ }
+ else if (HighRadio().IsChecked().Value())
+ {
+ priority = MeteredConnectionPriority::High;
+ }
+ request.Properties().Insert(HttpMeteredConnectionFilter::MeteredConnectionPriorityPropertyName(), box_value(priority));
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(httpClient.TrySendRequestAsync(request), cancellation);
+
+ if (result.Succeeded())
+ {
+ co_await Helpers::AddCancellation(Helpers::DisplayTextResultAsync(result.ResponseMessage(), OutputField()), cancellation);
+
+ rootPage.NotifyUser(L"Completed", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario14_MeteredConnectionFilter::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario14_MeteredConnectionFilter.h b/Samples/HttpClient/cppwinrt/Scenario14_MeteredConnectionFilter.h
new file mode 100644
index 0000000000..5b86304e7d
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario14_MeteredConnectionFilter.h
@@ -0,0 +1,45 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario14_MeteredConnectionFilter.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario14_MeteredConnectionFilter : Scenario14_MeteredConnectionFilterT
+ {
+ Scenario14_MeteredConnectionFilter();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ void OptInSwitch_Toggled(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ HttpFilters::HttpMeteredConnectionFilter meteredConnectionFilter{ nullptr };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Foundation::Uri resourceUri);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario14_MeteredConnectionFilter : Scenario14_MeteredConnectionFilterT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario15_ServerCertificateValidation.cpp b/Samples/HttpClient/cppwinrt/Scenario15_ServerCertificateValidation.cpp
new file mode 100644
index 0000000000..10ade6b094
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario15_ServerCertificateValidation.cpp
@@ -0,0 +1,217 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario15_ServerCertificateValidation.h"
+#include "Scenario15_ServerCertificateValidation.g.cpp"
+#include "Helpers.h"
+
+using namespace std::literals::chrono_literals;
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Security::Cryptography::Certificates;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+using namespace winrt::Windows::Web::Http;
+using namespace winrt::Windows::Web::Http::Filters;
+
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario15_ServerCertificateValidation::Scenario15_ServerCertificateValidation()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario15_ServerCertificateValidation::OnNavigatedTo(NavigationEventArgs const&)
+ {
+ filter = HttpBaseProtocolFilter();
+ httpClient = HttpClient(filter);
+ }
+
+ void Scenario15_ServerCertificateValidation::OnNavigatedFrom(NavigationEventArgs const&)
+ {
+ httpClient.Close();
+ filter.Close();
+ }
+
+ fire_and_forget Scenario15_ServerCertificateValidation::Start_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto lifetime = get_strong();
+
+ // The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
+ // valid, absolute URI, we'll notify the user about the incorrect input.
+ Uri resourceUri = Helpers::TryParseHttpUri(AddressField().Text());
+ if (!resourceUri)
+ {
+ rootPage.NotifyUser(L"Invalid URI.", NotifyType::ErrorMessage);
+ return;
+ }
+
+ Helpers::ScenarioStarted(StartButton(), CancelButton(), nullptr);
+ rootPage.NotifyUser(L"In progress", NotifyType::StatusMessage);
+
+ event_token customValidationToken{};
+ if (DefaultOSValidation().IsChecked().Value())
+ {
+ // Do nothing
+ }
+ else if (DefaultAndCustomValidation().IsChecked().Value())
+ {
+ // Add event handler to listen to the ServerCustomValidationRequested event. By default, OS validation
+ // will be performed before the event is raised.
+ customValidationToken = filter.ServerCustomValidationRequested({ get_weak(), &Scenario15_ServerCertificateValidation::MyCustomServerCertificateValidator });
+ }
+ else if (IgnoreErrorsAndCustomValidation().IsChecked().Value())
+ {
+ // ---------------------------------------------------------------------------
+ // WARNING: Only test applications should ignore SSL errors.
+ // In real applications, ignoring server certificate errors can lead to Man-In-The-Middle
+ // attacks (while the connection is secure, the server is not authenticated).
+ // Note that not all certificate validation errors can be ignored.
+ // ---------------------------------------------------------------------------
+ filter.IgnorableServerCertificateErrors().ReplaceAll({ ChainValidationResult::Untrusted, ChainValidationResult::InvalidName });
+
+ // Add event handler to listen to the ServerCustomValidationRequested event.
+ // This event handler must implement the desired custom certificate validation logic.
+ customValidationToken = filter.ServerCustomValidationRequested({ get_weak(), &Scenario15_ServerCertificateValidation::MyCustomServerCertificateValidator });
+ }
+
+ // Here, we turn off writing to and reading from the cache to ensure that each request actually
+ // hits the network and tries to establish an SSL/TLS connection with the server.
+ filter.CacheControl().WriteBehavior(HttpCacheWriteBehavior::NoCache);
+ filter.CacheControl().ReadBehavior(HttpCacheReadBehavior::NoCache);
+
+ HttpRequestMessage request(HttpMethod::Get(), resourceUri);
+
+ // This sample uses a "try" in order to support cancellation.
+ // If you don't need to support cancellation, then the "try" is not needed.
+ try
+ {
+ pendingAction = CancelableRequestAsync(request);
+ co_await pendingAction;
+ }
+ catch (hresult_canceled const&)
+ {
+ rootPage.NotifyUser(L"Request canceled.", NotifyType::ErrorMessage);
+ }
+
+ if (customValidationToken)
+ {
+ // Unregister the event handler after we are done validating.
+ filter.ServerCustomValidationRequested(customValidationToken);
+ }
+
+ Helpers::ScenarioCompleted(StartButton(), CancelButton());
+ }
+
+ IAsyncAction Scenario15_ServerCertificateValidation::CancelableRequestAsync(HttpRequestMessage request)
+ {
+ auto lifetime = get_strong();
+ auto cancellation = co_await get_cancellation_token();
+
+ HttpRequestResult result = co_await Helpers::AddCancellation(
+ httpClient.TrySendRequestAsync(request, HttpCompletionOption::ResponseHeadersRead), cancellation);
+
+ if (result.Succeeded())
+ {
+ rootPage.NotifyUser(L"Success - response received from server. Server certificate was valid.", NotifyType::StatusMessage);
+ }
+ else
+ {
+ Helpers::DisplayWebError(rootPage, result.ExtendedError());
+ }
+ }
+
+ void Scenario15_ServerCertificateValidation::Cancel_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (pendingAction)
+ {
+ pendingAction.Cancel();
+ }
+ }
+
+ // This event handler for server certificate validation executes synchronously as part of the SSL/TLS handshake.
+ // An app should not perform lengthy operations inside this handler. Otherwise, the remote server may terminate the connection abruptly.
+ fire_and_forget Scenario15_ServerCertificateValidation::MyCustomServerCertificateValidator(
+ HttpBaseProtocolFilter const&, HttpServerCustomValidationRequestedEventArgs args)
+ {
+ auto lifetime = get_strong();
+
+ // Get the server certificate and certificate chain from the args parameter.
+ Certificate serverCert = args.ServerCertificate();
+ IVectorView serverCertChain = args.ServerIntermediateCertificates();
+
+ // To illustrate the use of async APIs, we use the IsCertificateValidAsync method.
+ // In order to call async APIs in this handler, you must first take a deferral and then
+ // release it once you are done with the operation. In C++/WinRT, the deferral
+ // is released upon destruction, or you can hasten its release by calling the
+ // Complete() method prior to destruction.
+ Deferral deferral = args.GetDeferral();
+
+ try
+ {
+ bool isCertificateValid = co_await IsCertificateValidAsync(serverCert);
+ if (!isCertificateValid)
+ {
+ args.Reject();
+ }
+ }
+ catch (hresult_error const&)
+ {
+ // If we get an exception from IsCertificateValidAsync, we reject the certificate
+ // (secure by default).
+ args.Reject();
+ }
+ }
+
+ IAsyncOperation Scenario15_ServerCertificateValidation::IsCertificateValidAsync(Certificate serverCert)
+ {
+ auto lifetime = get_strong();
+
+ // This is a placeholder call to simulate long-running async calls. Note that this code runs synchronously as part of the SSL/TLS handshake.
+ // Avoid performing lengthy operations here - else, the remote server may terminate the connection abruptly.
+ co_await resume_after(100ms);
+
+ // In this sample, we compare the hash code of the certificate to a specific hash - this is purely
+ // for illustration purposes and should not be considered as a recommendation for certificate validation.
+ static constexpr std::array trustedHash{
+ 0x28, 0xb8, 0x85, 0x04, 0xf6, 0x09, 0xf6, 0x85, 0xf1, 0x68,
+ 0xb9, 0xa4, 0x9c, 0x8f, 0x0e, 0xc4, 0x9e, 0xad, 0x8b, 0xc2
+ };
+ if (serverCert.GetHashValue() == array_view(trustedHash))
+ {
+ // If certificate satisfies the criteria, return true.
+ co_return true;
+ }
+ else
+ {
+ // If certificate does not meet the required criteria, return false.
+ co_return false;
+ }
+ }
+
+ void Scenario15_ServerCertificateValidation::DefaultOSValidation_Checked(IInspectable const&, RoutedEventArgs const&)
+ {
+ AddressField().Text(L"https://www.microsoft.com");
+ }
+
+ void Scenario15_ServerCertificateValidation::DefaultAndCustomValidation_Checked(IInspectable const&, RoutedEventArgs const&)
+ {
+ AddressField().Text(L"https://www.microsoft.com");
+ }
+
+ void Scenario15_ServerCertificateValidation::IgnoreErrorsAndCustomValidation_Checked(IInspectable const&, RoutedEventArgs const&)
+ {
+ AddressField().Text(L"https://localhost/HttpClientSample/default.aspx");
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/Scenario15_ServerCertificateValidation.h b/Samples/HttpClient/cppwinrt/Scenario15_ServerCertificateValidation.h
new file mode 100644
index 0000000000..488f33317e
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/Scenario15_ServerCertificateValidation.h
@@ -0,0 +1,51 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario15_ServerCertificateValidation.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario15_ServerCertificateValidation : Scenario15_ServerCertificateValidationT
+ {
+ Scenario15_ServerCertificateValidation();
+
+ void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+ void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs const& e);
+
+ fire_and_forget Start_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void Cancel_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void DefaultOSValidation_Checked(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void DefaultAndCustomValidation_Checked(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+ void IgnoreErrorsAndCustomValidation_Checked(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ SDKTemplate::MainPage rootPage{ MainPage::Current() };
+ Windows::Web::Http::Filters::HttpBaseProtocolFilter filter{ nullptr };
+ Windows::Web::Http::HttpClient httpClient{ nullptr };
+ Windows::Foundation::IAsyncAction pendingAction{ nullptr };
+
+ Windows::Foundation::IAsyncAction CancelableRequestAsync(Windows::Web::Http::HttpRequestMessage request);
+ fire_and_forget MyCustomServerCertificateValidator(
+ Windows::Web::Http::Filters::HttpBaseProtocolFilter const& sender,
+ Windows::Web::Http::Filters::HttpServerCustomValidationRequestedEventArgs args);
+ Windows::Foundation::IAsyncOperation IsCertificateValidAsync(Windows::Security::Cryptography::Certificates::Certificate serverCert);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario15_ServerCertificateValidation : Scenario15_ServerCertificateValidationT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/SlowInputStream.cpp b/Samples/HttpClient/cppwinrt/SlowInputStream.cpp
new file mode 100644
index 0000000000..3fa35a8812
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/SlowInputStream.cpp
@@ -0,0 +1,51 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "SlowInputStream.h"
+#include "SlowInputStream.g.cpp"
+
+using namespace std::literals::chrono_literals;
+using namespace winrt;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Storage::Streams;
+
+namespace winrt::SDKTemplate::implementation
+{
+ IAsyncOperationWithProgress SlowInputStream::ReadAsync(IBuffer buffer, uint32_t count, InputStreamOptions options)
+ {
+ auto lifetime = get_strong();
+
+ // Introduce a 1 second delay.
+ co_await resume_after(1s);
+
+ uint32_t capacity = buffer.Capacity();
+ if (count > capacity)
+ {
+ count = capacity;
+ }
+
+ uint32_t available = m_length - m_position;
+ if (count > available)
+ {
+ count = available;
+ }
+
+ m_position += count;
+
+ memset(buffer.data(), '@', count);
+ buffer.Length(count);
+
+ (co_await get_progress_token())(count);
+
+ co_return buffer;
+ }
+}
diff --git a/Samples/HttpClient/cppwinrt/SlowInputStream.h b/Samples/HttpClient/cppwinrt/SlowInputStream.h
new file mode 100644
index 0000000000..6be550fc63
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/SlowInputStream.h
@@ -0,0 +1,34 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+#pragma once
+#include "SlowInputStream.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct SlowInputStream : SlowInputStreamT
+ {
+ SlowInputStream(uint32_t length) : m_length(length) { }
+ Windows::Foundation::IAsyncOperationWithProgress
+ ReadAsync(Windows::Storage::Streams::IBuffer buffer, uint32_t count, Windows::Storage::Streams::InputStreamOptions options);
+ void Close() { }
+
+ private:
+ uint32_t const m_length;
+ std::atomic m_position = 0;
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct SlowInputStream : SlowInputStreamT
+ {
+ };
+}
diff --git a/Samples/HttpClient/cppwinrt/packages.config b/Samples/HttpClient/cppwinrt/packages.config
new file mode 100644
index 0000000000..3407555859
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/cppwinrt/pch.cpp b/Samples/HttpClient/cppwinrt/pch.cpp
new file mode 100644
index 0000000000..01484ff5aa
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/pch.cpp
@@ -0,0 +1,6 @@
+//
+// pch.cpp
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/HttpClient/cppwinrt/pch.h b/Samples/HttpClient/cppwinrt/pch.h
new file mode 100644
index 0000000000..162f34b9cd
--- /dev/null
+++ b/Samples/HttpClient/cppwinrt/pch.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+#include "winrt/HttpFilters.h"
+#include "winrt/Windows.ApplicationModel.Activation.h"
+#include "winrt/Windows.Data.Json.h"
+#include "winrt/Windows.Data.Xml.Dom.h"
+#include "winrt/Windows.Foundation.h"
+#include "winrt/Windows.Foundation.Collections.h"
+#include "winrt/Windows.Security.Cryptography.h"
+#include "winrt/Windows.Security.Cryptography.Certificates.h"
+#include "winrt/Windows.Storage.Streams.h"
+#include "winrt/Windows.System.h"
+#include "winrt/Windows.UI.Core.h"
+#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.UI.Xaml.Automation.Peers.h"
+#include "winrt/Windows.UI.Xaml.Controls.h"
+#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
+#include "winrt/Windows.UI.Xaml.Documents.h"
+#include "winrt/Windows.UI.Xaml.Interop.h"
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.Xaml.Media.h"
+#include "winrt/Windows.UI.Xaml.Navigation.h"
+#include "winrt/Windows.Web.h"
+#include "winrt/Windows.Web.Http.h"
+#include "winrt/Windows.Web.Http.Filters.h"
+#include "winrt/Windows.Web.Http.Headers.h"
+#include
diff --git a/Samples/HttpClient/cs/Helpers.cs b/Samples/HttpClient/cs/Helpers.cs
index 23270fa459..b0cf6850da 100644
--- a/Samples/HttpClient/cs/Helpers.cs
+++ b/Samples/HttpClient/cs/Helpers.cs
@@ -80,22 +80,20 @@ internal static void SerializeHeaderCollection(
}
}
- internal static void CreateHttpClient(ref HttpClient httpClient)
+ internal static HttpClient CreateHttpClientWithPlugIn()
{
- if (httpClient != null)
- {
- httpClient.Dispose();
- }
// HttpClient functionality can be extended by plugging multiple filters together and providing
// HttpClient with the configured filter pipeline.
IHttpFilter filter = new HttpBaseProtocolFilter();
filter = new PlugInFilter(filter); // Adds a custom header to every request and response message.
- httpClient = new HttpClient(filter);
+ HttpClient httpClient = new HttpClient(filter);
// The following line sets a "User-Agent" request header as a default header on the HttpClient instance.
// Default headers will be sent with every request sent from this HttpClient instance.
httpClient.DefaultRequestHeaders.UserAgent.Add(new HttpProductInfoHeaderValue("Sample", "v8"));
+
+ return httpClient;
}
internal static void ScenarioStarted(Button startButton, Button cancelButton, TextBox outputField)
@@ -128,24 +126,25 @@ internal static void ReplaceQueryString(TextBox addressField, string newQueryStr
addressField.Text = resourceAddress + newQueryString;
}
- internal static bool TryGetUri(string uriString, out Uri uri)
+ internal static Uri TryParseHttpUri(string uriString)
{
// Note that this app has both "Internet (Client)" and "Home and Work Networking" capabilities set,
// since the user may provide URIs for servers located on the internet or intranet. If apps only
// communicate with servers on the internet, only the "Internet (Client)" capability should be set.
// Similarly if an app is only intended to communicate on the intranet, only the "Home and Work
// Networking" capability should be set.
+ Uri uri;
if (!Uri.TryCreate(uriString.Trim(), UriKind.Absolute, out uri))
{
- return false;
+ return null;
}
if (uri.Scheme != "http" && uri.Scheme != "https")
{
- return false;
+ return null;
}
- return true;
+ return uri;
}
}
}
diff --git a/Samples/HttpClient/cs/HttpClient.csproj b/Samples/HttpClient/cs/HttpClient.csproj
index e7e0d786bf..165e7b1ea7 100644
--- a/Samples/HttpClient/cs/HttpClient.csproj
+++ b/Samples/HttpClient/cs/HttpClient.csproj
@@ -124,32 +124,32 @@
..\shared\Scenario15_ServerCertificateValidation.xaml
-
- ..\shared\Scenario1_GetText.xaml
+
+ ..\shared\Scenario01_GetText.xaml
-
- ..\shared\Scenario2_GetStream.xaml
+
+ ..\shared\Scenario02_GetStream.xaml
-
- ..\shared\Scenario3_GetList.xaml
+
+ ..\shared\Scenario03_GetList.xaml
-
- ..\shared\Scenario4_PostText.xaml
+
+ ..\shared\Scenario04_PostText.xaml
-
- ..\shared\Scenario5_PostStream.xaml
+
+ ..\shared\Scenario05_PostStream.xaml
-
- ..\shared\Scenario6_PostMultipart.xaml
+
+ ..\shared\Scenario06_PostMultipart.xaml
-
- ..\shared\Scenario7_PostStreamWithProgress.xaml
+
+ ..\shared\Scenario07_PostStreamWithProgress.xaml
-
- ..\shared\Scenario8_PostCustomContent.xaml
+
+ ..\shared\Scenario08_PostCustomContent.xaml
-
- ..\shared\Scenario9_GetCookie.xaml
+
+ ..\shared\Scenario09_GetCookie.xaml
@@ -204,48 +204,48 @@
MSBuild:Compile
Designer
-
- Scenario1_GetText.xaml
+
+ Scenario01_GetText.xaml
MSBuild:Compile
Designer
-
- Scenario2_GetStream.xaml
+
+ Scenario02_GetStream.xaml
MSBuild:Compile
Designer
-
- Scenario3_GetList.xaml
+
+ Scenario03_GetList.xaml
MSBuild:Compile
Designer
-
- Scenario4_PostText.xaml
+
+ Scenario04_PostText.xaml
MSBuild:Compile
Designer
-
- Scenario5_PostStream.xaml
+
+ Scenario05_PostStream.xaml
MSBuild:Compile
Designer
-
- Scenario6_PostMultipart.xaml
+
+ Scenario06_PostMultipart.xaml
MSBuild:Compile
Designer
-
- Scenario7_PostStreamWithProgress.xaml
+
+ Scenario07_PostStreamWithProgress.xaml
MSBuild:Compile
Designer
-
- Scenario8_PostCustomContent.xaml
+
+ Scenario08_PostCustomContent.xaml
MSBuild:Compile
Designer
-
- Scenario9_GetCookie.xaml
+
+ Scenario09_GetCookie.xaml
MSBuild:Compile
Designer
@@ -298,4 +298,4 @@
-->
-
\ No newline at end of file
+
diff --git a/Samples/HttpClient/cs/HttpClient.sln b/Samples/HttpClient/cs/HttpClient.sln
index 160dedc8b2..785504b8e5 100644
--- a/Samples/HttpClient/cs/HttpClient.sln
+++ b/Samples/HttpClient/cs/HttpClient.sln
@@ -1,11 +1,11 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26228.4
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29920.165
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClient", "HttpClient.csproj", "{491F0942-0FCD-52C9-AB7D-5C6B952CC93A}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpFilters", "..\HttpFilters\HttpFilters.vcxproj", "{BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpFilters", "..\HttpFilters\HttpFilters.vcxproj", "{B31FB521-EBA9-5A64-93D7-4675DAE9845B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -35,20 +35,23 @@ Global
{491F0942-0FCD-52C9-AB7D-5C6B952CC93A}.Release|x86.ActiveCfg = Release|x86
{491F0942-0FCD-52C9-AB7D-5C6B952CC93A}.Release|x86.Build.0 = Release|x86
{491F0942-0FCD-52C9-AB7D-5C6B952CC93A}.Release|x86.Deploy.0 = Release|x86
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Debug|ARM.ActiveCfg = Debug|ARM
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Debug|ARM.Build.0 = Debug|ARM
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Debug|x64.ActiveCfg = Debug|x64
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Debug|x64.Build.0 = Debug|x64
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Debug|x86.ActiveCfg = Debug|Win32
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Debug|x86.Build.0 = Debug|Win32
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Release|ARM.ActiveCfg = Release|ARM
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Release|ARM.Build.0 = Release|ARM
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Release|x64.ActiveCfg = Release|x64
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Release|x64.Build.0 = Release|x64
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Release|x86.ActiveCfg = Release|Win32
- {BEEBA341-9D0E-5E14-BF1D-52C12AD7F8C1}.Release|x86.Build.0 = Release|Win32
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Debug|ARM.ActiveCfg = Debug|ARM
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Debug|ARM.Build.0 = Debug|ARM
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Debug|x64.ActiveCfg = Debug|x64
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Debug|x64.Build.0 = Debug|x64
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Debug|x86.ActiveCfg = Debug|Win32
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Debug|x86.Build.0 = Debug|Win32
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Release|ARM.ActiveCfg = Release|ARM
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Release|ARM.Build.0 = Release|ARM
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Release|x64.ActiveCfg = Release|x64
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Release|x64.Build.0 = Release|x64
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Release|x86.ActiveCfg = Release|Win32
+ {B31FB521-EBA9-5A64-93D7-4675DAE9845B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {7ECEA831-ED09-414C-A6C2-A492FD97A3E4}
+ EndGlobalSection
EndGlobal
diff --git a/Samples/HttpClient/cs/SampleConfiguration.cs b/Samples/HttpClient/cs/SampleConfiguration.cs
index a43a455796..8cc673c69c 100644
--- a/Samples/HttpClient/cs/SampleConfiguration.cs
+++ b/Samples/HttpClient/cs/SampleConfiguration.cs
@@ -23,21 +23,21 @@ public partial class MainPage : Page
List scenarios = new List
{
- new Scenario() { Title = "GET Text With Cache Control", ClassType = typeof(Scenario1) },
- new Scenario() { Title = "GET Stream", ClassType = typeof(Scenario2) },
- new Scenario() { Title = "GET List", ClassType = typeof(Scenario3) },
- new Scenario() { Title = "POST Text", ClassType = typeof(Scenario4) },
- new Scenario() { Title = "POST Stream", ClassType = typeof(Scenario5) },
- new Scenario() { Title = "POST Multipart", ClassType = typeof(Scenario6) },
- new Scenario() { Title = "POST Stream With Progress", ClassType = typeof(Scenario7) },
- new Scenario() { Title = "POST Custom Content", ClassType = typeof(Scenario8) },
- new Scenario() { Title = "Get Cookies", ClassType = typeof(Scenario9) },
- new Scenario() { Title = "Set Cookie", ClassType = typeof(Scenario10) },
- new Scenario() { Title = "Delete Cookie", ClassType = typeof(Scenario11) },
- new Scenario() { Title = "Disable Cookies", ClassType = typeof(Scenario12) },
- new Scenario() { Title = "Retry Filter", ClassType = typeof(Scenario13) },
- new Scenario() { Title = "Metered Connection Filter", ClassType = typeof(Scenario14) },
- new Scenario() { Title = "Server Certificate Validation", ClassType = typeof(Scenario15) },
+ new Scenario() { Title = "GET Text With Cache Control", ClassType = typeof(Scenario01_GetText) },
+ new Scenario() { Title = "GET Stream", ClassType = typeof(Scenario02_GetStream) },
+ new Scenario() { Title = "GET List", ClassType = typeof(Scenario03_GetList) },
+ new Scenario() { Title = "POST Text", ClassType = typeof(Scenario04_PostText) },
+ new Scenario() { Title = "POST Stream", ClassType = typeof(Scenario05_PostStream) },
+ new Scenario() { Title = "POST Multipart", ClassType = typeof(Scenario06_PostMultipart) },
+ new Scenario() { Title = "POST Stream With Progress", ClassType = typeof(Scenario07_PostStreamWithProgress) },
+ new Scenario() { Title = "POST Custom Content", ClassType = typeof(Scenario08_PostCustomContent) },
+ new Scenario() { Title = "Get Cookies", ClassType = typeof(Scenario09_GetCookie) },
+ new Scenario() { Title = "Set Cookie", ClassType = typeof(Scenario10_SetCookie) },
+ new Scenario() { Title = "Delete Cookie", ClassType = typeof(Scenario11_DeleteCookie) },
+ new Scenario() { Title = "Disable Cookies", ClassType = typeof(Scenario12_DisableCookies) },
+ new Scenario() { Title = "Retry Filter", ClassType = typeof(Scenario13_RetryFilter) },
+ new Scenario() { Title = "Metered Connection Filter", ClassType = typeof(Scenario14_MeteredConnectionFilter) },
+ new Scenario() { Title = "Server Certificate Validation", ClassType = typeof(Scenario15_ServerCertificateValidation) },
};
}
diff --git a/Samples/HttpClient/cs/Scenario1_GetText.xaml.cs b/Samples/HttpClient/cs/Scenario01_GetText.xaml.cs
similarity index 81%
rename from Samples/HttpClient/cs/Scenario1_GetText.xaml.cs
rename to Samples/HttpClient/cs/Scenario01_GetText.xaml.cs
index c53d611442..77e1fd08c6 100644
--- a/Samples/HttpClient/cs/Scenario1_GetText.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario01_GetText.xaml.cs
@@ -21,13 +21,8 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario1 : Page, IDisposable
+ public sealed partial class Scenario01_GetText : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpBaseProtocolFilter filter;
@@ -35,16 +30,11 @@ public sealed partial class Scenario1 : Page, IDisposable
private CancellationTokenSource cts;
private bool isFilterUsed;
- public Scenario1()
+ public Scenario01_GetText()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// In this scenario we just create an HttpClient instance with default settings. I.e. no custom filters.
@@ -68,23 +58,18 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
+ filter.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceUri;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceUri))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -134,12 +119,11 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
+ isFilterUsed = true;
HttpRequestResult result = await httpClient.TryGetAsync(resourceUri).AsTask(cts.Token);
if (result.Succeeded)
{
- isFilterUsed = true;
-
await Helpers.DisplayTextResultAsync(result.ResponseMessage, OutputField, cts.Token);
rootPage.NotifyUser(
@@ -168,27 +152,6 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
cts = new CancellationTokenSource();
}
- public void Dispose()
- {
- if (filter != null)
- {
- filter.Dispose();
- filter = null;
- }
-
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
-
private void MaxHttpVersionToggle_Toggled(object sender, RoutedEventArgs e)
{
HttpVersion httpVersion = HttpVersion.Http11;
diff --git a/Samples/HttpClient/cs/Scenario2_GetStream.xaml.cs b/Samples/HttpClient/cs/Scenario02_GetStream.xaml.cs
similarity index 76%
rename from Samples/HttpClient/cs/Scenario2_GetStream.xaml.cs
rename to Samples/HttpClient/cs/Scenario02_GetStream.xaml.cs
index 2c41f0cd80..e42c3bd093 100644
--- a/Samples/HttpClient/cs/Scenario2_GetStream.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario02_GetStream.xaml.cs
@@ -23,53 +23,37 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario2 : Page, IDisposable
+ public sealed partial class Scenario02_GetStream : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario2()
+ public Scenario02_GetStream()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
- Helpers.CreateHttpClient(ref httpClient);
+ httpClient = Helpers.CreateHttpClientWithPlugIn();
cts = new CancellationTokenSource();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -78,7 +62,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
Helpers.ScenarioStarted(StartButton, CancelButton, OutputField);
rootPage.NotifyUser("In progress", NotifyType.StatusMessage);
- HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceAddress);
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceUri);
// This sample uses a "try" in order to support TaskCanceledException.
// If you don't need to support cancellation, then the "try" is not needed.
@@ -139,20 +123,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario3_GetList.xaml.cs b/Samples/HttpClient/cs/Scenario03_GetList.xaml.cs
similarity index 69%
rename from Samples/HttpClient/cs/Scenario3_GetList.xaml.cs
rename to Samples/HttpClient/cs/Scenario03_GetList.xaml.cs
index 0544b487c9..cf1f63df48 100644
--- a/Samples/HttpClient/cs/Scenario3_GetList.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario03_GetList.xaml.cs
@@ -21,53 +21,37 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario3 : Page, IDisposable
+ public sealed partial class Scenario03_GetList : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario3()
+ public Scenario03_GetList()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
- Helpers.CreateHttpClient(ref httpClient);
+ httpClient = Helpers.CreateHttpClientWithPlugIn();
cts = new CancellationTokenSource();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -80,7 +64,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryGetAsync(resourceAddress).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryGetAsync(resourceUri).AsTask(cts.Token);
if (result.Succeeded)
{
@@ -115,20 +99,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario4_PostText.xaml.cs b/Samples/HttpClient/cs/Scenario04_PostText.xaml.cs
similarity index 67%
rename from Samples/HttpClient/cs/Scenario4_PostText.xaml.cs
rename to Samples/HttpClient/cs/Scenario04_PostText.xaml.cs
index 273cd13536..ce0ef4312e 100644
--- a/Samples/HttpClient/cs/Scenario4_PostText.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario04_PostText.xaml.cs
@@ -19,53 +19,37 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario4 : Page, IDisposable
+ public sealed partial class Scenario04_PostText : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario4()
+ public Scenario04_PostText()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
- Helpers.CreateHttpClient(ref httpClient);
+ httpClient = Helpers.CreateHttpClientWithPlugIn();
cts = new CancellationTokenSource();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -78,7 +62,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryPostAsync(resourceAddress,
+ HttpRequestResult result = await httpClient.TryPostAsync(resourceUri,
new HttpStringContent(RequestBodyField.Text)).AsTask(cts.Token);
if (result.Succeeded)
@@ -108,20 +92,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario5_PostStream.xaml.cs b/Samples/HttpClient/cs/Scenario05_PostStream.xaml.cs
similarity index 71%
rename from Samples/HttpClient/cs/Scenario5_PostStream.xaml.cs
rename to Samples/HttpClient/cs/Scenario05_PostStream.xaml.cs
index 4f23b1ca2f..8eab761ad4 100644
--- a/Samples/HttpClient/cs/Scenario5_PostStream.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario05_PostStream.xaml.cs
@@ -20,53 +20,37 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario5 : Page, IDisposable
+ public sealed partial class Scenario05_PostStream : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario5()
+ public Scenario05_PostStream()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
- Helpers.CreateHttpClient(ref httpClient);
+ httpClient = Helpers.CreateHttpClientWithPlugIn();
cts = new CancellationTokenSource();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -79,7 +63,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
Stream stream = GenerateSampleStream(contentLength);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
- HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, resourceAddress);
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, resourceUri);
request.Content = streamContent;
// This sample uses a "try" in order to support TaskCanceledException.
@@ -128,20 +112,5 @@ private static MemoryStream GenerateSampleStream(int size)
return new MemoryStream(subData);
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario6_PostMultipart.xaml.cs b/Samples/HttpClient/cs/Scenario06_PostMultipart.xaml.cs
similarity index 67%
rename from Samples/HttpClient/cs/Scenario6_PostMultipart.xaml.cs
rename to Samples/HttpClient/cs/Scenario06_PostMultipart.xaml.cs
index 996ed87821..634455d208 100644
--- a/Samples/HttpClient/cs/Scenario6_PostMultipart.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario06_PostMultipart.xaml.cs
@@ -19,53 +19,36 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario6 : Page, IDisposable
+ public sealed partial class Scenario06_PostMultipart : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
-
- public Scenario6()
+ public Scenario06_PostMultipart()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
- Helpers.CreateHttpClient(ref httpClient);
+ httpClient = Helpers.CreateHttpClientWithPlugIn();
cts = new CancellationTokenSource();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -81,7 +64,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryPostAsync(resourceAddress, form).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryPostAsync(resourceUri, form).AsTask(cts.Token);
if (result.Succeeded)
{
@@ -110,20 +93,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario7_PostStreamWithProgress.xaml.cs b/Samples/HttpClient/cs/Scenario07_PostStreamWithProgress.xaml.cs
similarity index 81%
rename from Samples/HttpClient/cs/Scenario7_PostStreamWithProgress.xaml.cs
rename to Samples/HttpClient/cs/Scenario07_PostStreamWithProgress.xaml.cs
index 84d0341439..94333d5e21 100644
--- a/Samples/HttpClient/cs/Scenario7_PostStreamWithProgress.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario07_PostStreamWithProgress.xaml.cs
@@ -20,28 +20,18 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario7 : Page, IDisposable
+ public sealed partial class Scenario07_PostStreamWithProgress : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario7()
+ public Scenario07_PostStreamWithProgress()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
httpClient = new HttpClient();
@@ -51,14 +41,9 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private void UpdateAddressField()
@@ -80,11 +65,10 @@ private void ChunkedResponseToggle_Toggled(object sender, RoutedEventArgs e)
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -109,7 +93,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryPostAsync(resourceAddress, streamContent).AsTask(cts.Token, progress);
+ HttpRequestResult result = await httpClient.TryPostAsync(resourceUri, streamContent).AsTask(cts.Token, progress);
if (result.Succeeded)
{
@@ -200,20 +184,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario8_PostCustomContent.xaml.cs b/Samples/HttpClient/cs/Scenario08_PostCustomContent.xaml.cs
similarity index 68%
rename from Samples/HttpClient/cs/Scenario8_PostCustomContent.xaml.cs
rename to Samples/HttpClient/cs/Scenario08_PostCustomContent.xaml.cs
index 219eebf161..4395ea6703 100644
--- a/Samples/HttpClient/cs/Scenario8_PostCustomContent.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario08_PostCustomContent.xaml.cs
@@ -20,28 +20,18 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario8 : Page, IDisposable
+ public sealed partial class Scenario08_PostCustomContent : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario8()
+ public Scenario08_PostCustomContent()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
httpClient = new HttpClient();
@@ -50,23 +40,17 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -81,7 +65,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryPostAsync(resourceAddress, jsonContent).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryPostAsync(resourceUri, jsonContent).AsTask(cts.Token);
if (result.Succeeded)
{
@@ -110,20 +94,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario9_GetCookie.xaml.cs b/Samples/HttpClient/cs/Scenario09_GetCookie.xaml.cs
similarity index 71%
rename from Samples/HttpClient/cs/Scenario9_GetCookie.xaml.cs
rename to Samples/HttpClient/cs/Scenario09_GetCookie.xaml.cs
index e09a10f3f3..91d0a5bcb7 100644
--- a/Samples/HttpClient/cs/Scenario9_GetCookie.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario09_GetCookie.xaml.cs
@@ -20,59 +20,44 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario9 : Page, IDisposable
+ public sealed partial class Scenario09_GetCookie : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario9()
+ public Scenario09_GetCookie()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
- Helpers.CreateHttpClient(ref httpClient);
+ httpClient = Helpers.CreateHttpClientWithPlugIn();
cts = new CancellationTokenSource();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private void GetCookies_Click(object sender, RoutedEventArgs e)
{
- try
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
- Uri resourceAddress;
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
- {
- rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
- return;
- }
+ rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
+ return;
+ }
+ try
+ {
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
- HttpCookieCollection cookieCollection = filter.CookieManager.GetCookies(resourceAddress);
+ HttpCookieCollection cookieCollection = filter.CookieManager.GetCookies(resourceUri);
OutputField.Text = cookieCollection.Count + " cookies found.\r\n";
foreach (HttpCookie cookie in cookieCollection)
@@ -95,11 +80,10 @@ private void GetCookies_Click(object sender, RoutedEventArgs e)
private async void SendHttpGetButton_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -112,7 +96,7 @@ private async void SendHttpGetButton_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryGetAsync(resourceAddress).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryGetAsync(resourceUri).AsTask(cts.Token);
if (result.Succeeded)
{
@@ -141,20 +125,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario10_SetCookie.xaml.cs b/Samples/HttpClient/cs/Scenario10_SetCookie.xaml.cs
index fbaa66fe27..a4b66ffd64 100644
--- a/Samples/HttpClient/cs/Scenario10_SetCookie.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario10_SetCookie.xaml.cs
@@ -18,29 +18,15 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario10 : Page
+ public sealed partial class Scenario10_SetCookie : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
- public Scenario10()
+ public Scenario10_SetCookie()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
- protected override void OnNavigatedTo(NavigationEventArgs e)
- {
- }
-
private void SetCookie_Click(object sender, RoutedEventArgs e)
{
if (String.IsNullOrEmpty(NameField.Text) || String.IsNullOrEmpty(DomainField.Text) || String.IsNullOrEmpty(PathField.Text))
diff --git a/Samples/HttpClient/cs/Scenario11_DeleteCookie.xaml.cs b/Samples/HttpClient/cs/Scenario11_DeleteCookie.xaml.cs
index e7181f7a49..3496afec97 100644
--- a/Samples/HttpClient/cs/Scenario11_DeleteCookie.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario11_DeleteCookie.xaml.cs
@@ -21,26 +21,17 @@ namespace SDKTemplate
///
/// An empty page that can be used on its own or navigated to within a Frame.
///
- public sealed partial class Scenario11 : Page
+ public sealed partial class Scenario11_DeleteCookie : Page
{
// A pointer back to the main page. This is needed if you want to call methods in MainPage such
// as NotifyUser()
MainPage rootPage = MainPage.Current;
- public Scenario11()
+ public Scenario11_DeleteCookie()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
- protected override void OnNavigatedTo(NavigationEventArgs e)
- {
- }
-
private void DeleteCookie_Click(object sender, RoutedEventArgs e)
{
if (String.IsNullOrEmpty(NameField.Text) || String.IsNullOrEmpty(DomainField.Text) || String.IsNullOrEmpty(PathField.Text))
diff --git a/Samples/HttpClient/cs/Scenario12_DisableCookies.xaml.cs b/Samples/HttpClient/cs/Scenario12_DisableCookies.xaml.cs
index c9e7ff7ecf..a393c3c186 100644
--- a/Samples/HttpClient/cs/Scenario12_DisableCookies.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario12_DisableCookies.xaml.cs
@@ -18,24 +18,17 @@
using Windows.Web.Http;
using Windows.Web.Http.Filters;
-// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
-
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario12 : Page, IDisposable
+ public sealed partial class Scenario12_DisableCookies : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpBaseProtocolFilter filter;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario12()
+ public Scenario12_DisableCookies()
{
this.InitializeComponent();
}
@@ -49,22 +42,18 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
+ filter.Dispose();
}
+
private async void SendInitialGetButton_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -75,11 +64,11 @@ private async void SendInitialGetButton_Click(object sender, RoutedEventArgs e)
try
{
- HttpRequestResult result = await httpClient.TryGetAsync(resourceAddress).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryGetAsync(resourceUri).AsTask(cts.Token);
if (result.Succeeded)
{
- HttpCookieCollection cookieCollection = filter.CookieManager.GetCookies(resourceAddress);
+ HttpCookieCollection cookieCollection = filter.CookieManager.GetCookies(resourceUri);
OutputField.Text = cookieCollection.Count + " cookies found.\r\n";
foreach (HttpCookie cookie in cookieCollection)
{
@@ -111,11 +100,11 @@ private async void SendInitialGetButton_Click(object sender, RoutedEventArgs e)
private async void SendNextRequestButton_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -138,7 +127,7 @@ private async void SendNextRequestButton_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryGetAsync(resourceAddress).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryGetAsync(resourceUri).AsTask(cts.Token);
if (result.Succeeded)
{
@@ -170,23 +159,6 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
public void Dispose()
{
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
-
- if(filter != null)
- {
- filter.Dispose();
- filter = null;
- }
}
}
}
\ No newline at end of file
diff --git a/Samples/HttpClient/cs/Scenario13_RetryFilter.xaml.cs b/Samples/HttpClient/cs/Scenario13_RetryFilter.xaml.cs
index 5c78e256db..ad80d8aaf7 100644
--- a/Samples/HttpClient/cs/Scenario13_RetryFilter.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario13_RetryFilter.xaml.cs
@@ -21,28 +21,18 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario13 : Page, IDisposable
+ public sealed partial class Scenario13_RetryFilter : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario13()
+ public Scenario13_RetryFilter()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
HttpBaseProtocolFilter baseProtocolFilter = new HttpBaseProtocolFilter();
@@ -54,14 +44,9 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
}
private void UpdateAddressField()
@@ -87,11 +72,11 @@ private void RetryAfterSwitch_Toggled(object sender, RoutedEventArgs e)
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -104,7 +89,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestResult result = await httpClient.TryGetAsync(resourceAddress).AsTask(cts.Token);
+ HttpRequestResult result = await httpClient.TryGetAsync(resourceUri).AsTask(cts.Token);
if (result.Succeeded)
{
@@ -133,20 +118,5 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
// Re-create the CancellationTokenSource.
cts = new CancellationTokenSource();
}
-
- public void Dispose()
- {
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
}
}
diff --git a/Samples/HttpClient/cs/Scenario14_MeteredConnectionFilter.xaml.cs b/Samples/HttpClient/cs/Scenario14_MeteredConnectionFilter.xaml.cs
index 0a52566b4e..38164b7c68 100644
--- a/Samples/HttpClient/cs/Scenario14_MeteredConnectionFilter.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario14_MeteredConnectionFilter.xaml.cs
@@ -21,20 +21,15 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario14 : Page, IDisposable
+ public sealed partial class Scenario14_MeteredConnectionFilter : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpMeteredConnectionFilter meteredConnectionFilter;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario14()
+ public Scenario14_MeteredConnectionFilter()
{
this.InitializeComponent();
}
@@ -49,24 +44,18 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- base.OnNavigatedFrom(e);
- Dispose();
+ cts.Cancel();
+ cts.Dispose();
+ httpClient.Dispose();
+ meteredConnectionFilter.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -75,23 +64,23 @@ private async void Start_Click(object sender, RoutedEventArgs e)
Helpers.ScenarioStarted(StartButton, CancelButton, OutputField);
rootPage.NotifyUser("In progress", NotifyType.StatusMessage);
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceUri);
+
+ MeteredConnectionPriority priority = MeteredConnectionPriority.Low;
+ if (MediumRadio.IsChecked.Value)
+ {
+ priority = MeteredConnectionPriority.Medium;
+ }
+ else if (HighRadio.IsChecked.Value)
+ {
+ priority = MeteredConnectionPriority.High;
+ }
+ request.Properties[HttpMeteredConnectionFilter.MeteredConnectionPriorityPropertyName] = priority;
+
// This sample uses a "try" in order to support TaskCanceledException.
// If you don't need to support cancellation, then the "try" is not needed.
try
{
- HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceAddress);
-
- MeteredConnectionPriority priority = MeteredConnectionPriority.Low;
- if (MediumRadio.IsChecked.Value)
- {
- priority = MeteredConnectionPriority.Medium;
- }
- else if (HighRadio.IsChecked.Value)
- {
- priority = MeteredConnectionPriority.High;
- }
- request.Properties["meteredConnectionPriority"] = priority;
-
HttpRequestResult result = await httpClient.TrySendRequestAsync(request).AsTask(cts.Token);
if (result.Succeeded)
@@ -122,26 +111,6 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
cts = new CancellationTokenSource();
}
- public void Dispose()
- {
- if (meteredConnectionFilter != null)
- {
- meteredConnectionFilter.Dispose();
- meteredConnectionFilter = null;
- }
- if (httpClient != null)
- {
- httpClient.Dispose();
- httpClient = null;
- }
-
- if (cts != null)
- {
- cts.Dispose();
- cts = null;
- }
- }
-
private void OptInSwitch_Toggled(object sender, RoutedEventArgs e)
{
meteredConnectionFilter.OptIn = OptInSwitch.IsOn;
diff --git a/Samples/HttpClient/cs/Scenario15_ServerCertificateValidation.xaml.cs b/Samples/HttpClient/cs/Scenario15_ServerCertificateValidation.xaml.cs
index d1702995fc..4a1b05a078 100644
--- a/Samples/HttpClient/cs/Scenario15_ServerCertificateValidation.xaml.cs
+++ b/Samples/HttpClient/cs/Scenario15_ServerCertificateValidation.xaml.cs
@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
@@ -24,28 +25,19 @@
namespace SDKTemplate
{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class Scenario15 : Page, IDisposable
+ public sealed partial class Scenario15_ServerCertificateValidation : Page
{
- // A pointer back to the main page. This is needed if you want to call methods in MainPage such
- // as NotifyUser()
MainPage rootPage = MainPage.Current;
private HttpBaseProtocolFilter filter;
private HttpClient httpClient;
private CancellationTokenSource cts;
- public Scenario15()
+
+ public Scenario15_ServerCertificateValidation()
{
this.InitializeComponent();
}
- ///
- /// Invoked when this page is about to be displayed in a Frame.
- ///
- /// Event data that describes how this page was reached. The Parameter
- /// property is typically used to configure the page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// In this scenario we just create an HttpClient instance with default settings. I.e. no custom filters.
@@ -57,23 +49,17 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
- // If the navigation is external to the app do not clean up.
- // This can occur on Phone when suspending the app.
- if (e.NavigationMode == NavigationMode.Forward && e.Uri == null)
- {
- return;
- }
-
- Dispose();
+ cts.Dispose();
+ httpClient.Dispose();
+ filter.Dispose();
}
private async void Start_Click(object sender, RoutedEventArgs e)
{
- Uri resourceAddress;
-
// The value of 'AddressField' is set by the user and is therefore untrusted input. If we can't create a
// valid, absolute URI, we'll notify the user about the incorrect input.
- if (!Helpers.TryGetUri(AddressField.Text, out resourceAddress))
+ Uri resourceUri = Helpers.TryParseHttpUri(AddressField.Text);
+ if (resourceUri == null)
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
@@ -116,7 +102,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.NoCache;
- HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceAddress);
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceUri);
// This sample uses a "try" in order to support TaskCanceledException.
// If you don't need to support cancellation, then the "try" is not needed.
@@ -133,9 +119,7 @@ private async void Start_Click(object sender, RoutedEventArgs e)
}
else
{
-
Helpers.DisplayWebError(rootPage, result.ExtendedError);
-
}
}
catch (TaskCanceledException)
@@ -161,18 +145,6 @@ private void Cancel_Click(object sender, RoutedEventArgs e)
cts = new CancellationTokenSource();
}
- public void Dispose()
- {
- httpClient?.Dispose();
- httpClient = null;
-
- cts?.Dispose();
- cts = null;
-
- filter?.Dispose();
- filter = null;
- }
-
// This event handler for server certificate validation executes synchronously as part of the SSL/TLS handshake.
// An app should not perform lengthy operations inside this handler. Otherwise, the remote server may terminate the connection abruptly.
private async void MyCustomServerCertificateValidator(HttpBaseProtocolFilter sender, HttpServerCustomValidationRequestedEventArgs args)
@@ -210,10 +182,13 @@ private async Task IsCertificateValidAsync(Certificate serverCert)
// Avoid performing lengthy operations here - else, the remote server may terminate the connection abruptly.
await Task.Delay(100);
- // In this sample, we compare the hash code of the certificate to a specific integer - this is purely
+ // In this sample, we compare the hash code of the certificate to a specific hash - this is purely
// for illustration purposes and should not be considered as a recommendation for certificate validation.
- const int trustedHashCode = 6044116;
- if (serverCert.GetHashCode().Equals(trustedHashCode))
+ var trustedHash = new byte[] {
+ 0x28, 0xb8, 0x85, 0x04, 0xf6, 0x09, 0xf6, 0x85, 0xf1, 0x68,
+ 0xb9, 0xa4, 0x9c, 0x8f, 0x0e, 0xc4, 0x9e, 0xad, 0x8b, 0xc2
+ };
+ if (serverCert.GetHashValue().SequenceEqual(trustedHash))
{
// If certificate satisfies the criteria, return true.
return true;
@@ -240,6 +215,4 @@ private void IgnoreErrorsAndCustomValidation_Checked(object sender, RoutedEventA
AddressField.Text = "https://localhost/HttpClientSample/default.aspx";
}
}
-
-
}
diff --git a/Samples/HttpClient/shared/Scenario01_GetText.xaml b/Samples/HttpClient/shared/Scenario01_GetText.xaml
new file mode 100644
index 0000000000..54fdfa9435
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario01_GetText.xaml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Download the contents of a page and display it. One way to test Cancel
+ functionality is to change the hostname in the Address from localhost to
+ a name that does not exist. To test cache control, change the cache read
+ behavior or the cache write behavior. Use the Max HTTP Version toggle to
+ control the highest HTTP version the client will offer - note that the
+ version that is actually used will also depend on the server and intermediate
+ proxies.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default (if it is already in the cache, does not hit the network)
+
+
+
+ Most Recent (always hits the network, but if it is already in the
+ cache, If-Modified-Since header is added automatically and if
+ server does not have a newer version, the server will reply with
+ 304 and network bandwidth will be saved)
+
+
+
+ Only From Cache (never hits the network)
+
+
+ No Cache (always hits the network)
+
+
+
+
+ Default (if cacheable, stored in the cache)
+
+
+ No Cache (never stored in the cache)
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario02_GetStream.xaml b/Samples/HttpClient/shared/Scenario02_GetStream.xaml
new file mode 100644
index 0000000000..9316d7a52f
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario02_GetStream.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Download an unbuffered stream of data.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario03_GetList.xaml b/Samples/HttpClient/shared/Scenario03_GetList.xaml
new file mode 100644
index 0000000000..fcb0383080
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario03_GetList.xaml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Download an XML file and display the results in a list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario04_PostText.xaml b/Samples/HttpClient/shared/Scenario04_PostText.xaml
new file mode 100644
index 0000000000..3569a70436
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario04_PostText.xaml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario05_PostStream.xaml b/Samples/HttpClient/shared/Scenario05_PostStream.xaml
new file mode 100644
index 0000000000..2e456fd856
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario05_PostStream.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload a stream of data.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario06_PostMultipart.xaml b/Samples/HttpClient/shared/Scenario06_PostMultipart.xaml
new file mode 100644
index 0000000000..9d1f20fdd2
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario06_PostMultipart.xaml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload a MIME form using the MultipartFormDataContent class.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario07_PostStreamWithProgress.xaml b/Samples/HttpClient/shared/Scenario07_PostStreamWithProgress.xaml
new file mode 100644
index 0000000000..0e2911c386
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario07_PostStreamWithProgress.xaml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ POST a stream and download content from a website. Use the progress
+ handler to get information about the stage, retries made, data sent and
+ data received.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario08_PostCustomContent.xaml b/Samples/HttpClient/shared/Scenario08_PostCustomContent.xaml
new file mode 100644
index 0000000000..6efdc6a49b
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario08_PostCustomContent.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload a JSON string using a custom content type.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario09_GetCookie.xaml b/Samples/HttpClient/shared/Scenario09_GetCookie.xaml
new file mode 100644
index 0000000000..db33acb132
--- /dev/null
+++ b/Samples/HttpClient/shared/Scenario09_GetCookie.xaml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Get the cookies that will be sent if a request is sent to the given
+ address. Press the Send HTTP GET button to send a GET request to the
+ test server. The test server will reply with two Set-Cookie headers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario10_SetCookie.xaml b/Samples/HttpClient/shared/Scenario10_SetCookie.xaml
index 77bfb22e72..8b7419c69c 100644
--- a/Samples/HttpClient/shared/Scenario10_SetCookie.xaml
+++ b/Samples/HttpClient/shared/Scenario10_SetCookie.xaml
@@ -10,7 +10,13 @@
//
//*********************************************************
-->
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add a cookie in the cookie store or replace it if it already exists.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/archived/HttpClient/shared/Scenario11_DeleteCookie.xaml b/archived/HttpClient/shared/Scenario11_DeleteCookie.xaml
new file mode 100644
index 0000000000..10e3edc670
--- /dev/null
+++ b/archived/HttpClient/shared/Scenario11_DeleteCookie.xaml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Delete a cookie from the cookie store.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/archived/HttpClient/shared/Scenario12_DisableCookies.xaml b/archived/HttpClient/shared/Scenario12_DisableCookies.xaml
new file mode 100644
index 0000000000..55e1eb2006
--- /dev/null
+++ b/archived/HttpClient/shared/Scenario12_DisableCookies.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Send a request to a given address with or without previously received cookies attached to it. First, use the Send initial request button to send a request to the
+ test server, and get a response with two cookies. Then, choose if you want to send the next request with or without those cookies. The test server response mirrors
+ the client request and you can look for the 'Cookie' header to check if cookies were sent to the server or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/archived/HttpClient/shared/Scenario13_RetryFilter.xaml b/archived/HttpClient/shared/Scenario13_RetryFilter.xaml
new file mode 100644
index 0000000000..c3aca4e0ce
--- /dev/null
+++ b/archived/HttpClient/shared/Scenario13_RetryFilter.xaml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Download the contents of a page and display it. If a server replies
+ with a 503 Service Unavailable HTTP status and includes a Reply-After
+ header, the Retry Filter will send the request again as the Retry-After
+ header indicates. Use the toggle switch to modify the test server response.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/archived/HttpClient/shared/Scenario14_MeteredConnectionFilter.xaml b/archived/HttpClient/shared/Scenario14_MeteredConnectionFilter.xaml
new file mode 100644
index 0000000000..9eeb6bd5e0
--- /dev/null
+++ b/archived/HttpClient/shared/Scenario14_MeteredConnectionFilter.xaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Metered Connection Filter sends all requests while in Normal mode,
+ only medium and high priority requests while in Conservative mode and
+ only high priority requests if the app opts in while in Opt-In mode.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/archived/HttpClient/shared/Scenario15_ServerCertificateValidation.xaml b/archived/HttpClient/shared/Scenario15_ServerCertificateValidation.xaml
new file mode 100644
index 0000000000..336e2a1a19
--- /dev/null
+++ b/archived/HttpClient/shared/Scenario15_ServerCertificateValidation.xaml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Send an HTTP request to an https:// URI, and validate the X509 Certificate that the server presents.
+ You can choose to use either the default OS validation, or ignore some of the errors therein and/or
+ add your own custom validation of the certificate (e.g. certificate pinning). This sample's custom
+ validation handler rejects all server certificates, so errors are expected to occur during connection
+ establishment in cases where the custom validation logic is enabled.
+
+
+
+
+
+
+
+ Default OS validation
+
+
+
+
+ OS validation + Custom validation (e.g. Certificate Pinning)
+
+
+
+
+ Ignore OS validation errors + Custom validation
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HttpClient/shared/Scenario1_GetText.xaml b/archived/HttpClient/shared/Scenario1_GetText.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario1_GetText.xaml
rename to archived/HttpClient/shared/Scenario1_GetText.xaml
diff --git a/Samples/HttpClient/shared/Scenario2_GetStream.xaml b/archived/HttpClient/shared/Scenario2_GetStream.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario2_GetStream.xaml
rename to archived/HttpClient/shared/Scenario2_GetStream.xaml
diff --git a/Samples/HttpClient/shared/Scenario3_GetList.xaml b/archived/HttpClient/shared/Scenario3_GetList.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario3_GetList.xaml
rename to archived/HttpClient/shared/Scenario3_GetList.xaml
diff --git a/Samples/HttpClient/shared/Scenario4_PostText.xaml b/archived/HttpClient/shared/Scenario4_PostText.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario4_PostText.xaml
rename to archived/HttpClient/shared/Scenario4_PostText.xaml
diff --git a/Samples/HttpClient/shared/Scenario5_PostStream.xaml b/archived/HttpClient/shared/Scenario5_PostStream.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario5_PostStream.xaml
rename to archived/HttpClient/shared/Scenario5_PostStream.xaml
diff --git a/Samples/HttpClient/shared/Scenario6_PostMultipart.xaml b/archived/HttpClient/shared/Scenario6_PostMultipart.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario6_PostMultipart.xaml
rename to archived/HttpClient/shared/Scenario6_PostMultipart.xaml
diff --git a/Samples/HttpClient/shared/Scenario7_PostStreamWithProgress.xaml b/archived/HttpClient/shared/Scenario7_PostStreamWithProgress.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario7_PostStreamWithProgress.xaml
rename to archived/HttpClient/shared/Scenario7_PostStreamWithProgress.xaml
diff --git a/Samples/HttpClient/shared/Scenario8_PostCustomContent.xaml b/archived/HttpClient/shared/Scenario8_PostCustomContent.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario8_PostCustomContent.xaml
rename to archived/HttpClient/shared/Scenario8_PostCustomContent.xaml
diff --git a/Samples/HttpClient/shared/Scenario9_GetCookie.xaml b/archived/HttpClient/shared/Scenario9_GetCookie.xaml
similarity index 100%
rename from Samples/HttpClient/shared/Scenario9_GetCookie.xaml
rename to archived/HttpClient/shared/Scenario9_GetCookie.xaml
diff --git a/archived/LinguisticServices/README.md b/archived/LinguisticServices/README.md
index e0ba6c1347..944ebdb995 100644
--- a/archived/LinguisticServices/README.md
+++ b/archived/LinguisticServices/README.md
@@ -1,5 +1,5 @@
---
-page_type: sample
+topic: sample
languages:
- cpp
- cppcx
diff --git a/archived/TouchKeyboard/README.md b/archived/TouchKeyboard/README.md
new file mode 100644
index 0000000000..822c0f66c1
--- /dev/null
+++ b/archived/TouchKeyboard/README.md
@@ -0,0 +1,80 @@
+---
+topic: sample
+languages:
+- cpp
+- cppcx
+products:
+- windows
+- windows-uwp
+urlFragment: TouchKeyboard
+extendedZipContent:
+- path: SharedContent
+ target: SharedContent
+- path: LICENSE
+ target: LICENSE
+description: "Shows both the default display behavior of the touch keyboard and how that behavior can be customized in a UWP app."
+---
+
+
+
+# Touch keyboard sample
+
+Shows both the default display behavior of the touch keyboard and how that behavior can be customized in a UWP app.
+
+> **Note:** This sample is part of a large collection of UWP feature samples.
+> You can download this sample as a standalone ZIP file
+> [from docs.microsoft.com](https://docs.microsoft.com/samples/microsoft/windows-universal-samples/touchkeyboard/),
+> or you can download the entire collection as a single
+> [ZIP file](https://github.com/Microsoft/Windows-universal-samples/archive/master.zip), but be
+> sure to unzip everything to access shared dependencies. For more info on working with the ZIP file,
+> the samples collection, and GitHub, see [Get the UWP samples from GitHub](https://aka.ms/ovu2uq).
+> For more samples, see the [Samples portal](https://aka.ms/winsamples) on the Windows Dev Center.
+
+Specifically, this sample shows how:
+
+* XAML text controls (such as TextBox, RichTextBox, and PaswordBox) display the touch keyboard by default.
+* Controls derived from XAML text controls display the touch keyboard by default.
+* Apps can subscribe to events indicating when the touch keyboard is shown and hidden.
+* Apps can request that the touch keyboard be shown or hidden.
+
+**Note** The touch keyboard does not automatically display if a hardware keyboard is connected,
+or the device is in Desktop mode and "Show the touch keyboard when not in tablet mode and there's no keyboard attached" is set to "Off" in **Settings -> Devices -> Typing**.
+
+**Note** The Windows universal samples require Visual Studio to build and Windows 10 to execute.
+
+**Note** Custom text edit control sample shows how to manage the visibility of the touch keyboard programatically.
+
+To obtain information about Windows 10, go to [Windows 10](http://go.microsoft.com/fwlink/?LinkID=532421)
+
+To obtain information about Microsoft Visual Studio and the tools for developing Windows apps, go to [Visual Studio](http://go.microsoft.com/fwlink/?LinkID=532422)
+
+## System requirements
+
+**Client:** Windows 10
+
+**Server:** Windows Server 2016 Technical Preview
+
+**Phone:** Windows 10. (KeyboardEnabledTextBox not supported; see remarks above.)
+
+## Build the sample
+
+1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**.
+2. Go to the directory to which you unzipped the sample. Then go to the subdirectory containing the sample in the language you desire - either C++, C#, or JavaScript. Double-click the Visual Studio Solution (.sln) file.
+3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+## Run the sample
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+### Deploying the sample
+
+- Select Build > Deploy Solution.
+
+### Deploying and running the sample
+
+- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or select Debug > Start Without Debugging.
+
+
diff --git a/Samples/TouchKeyboard/cpp/Package.appxmanifest b/archived/TouchKeyboard/cpp/Package.appxmanifest
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Package.appxmanifest
rename to archived/TouchKeyboard/cpp/Package.appxmanifest
diff --git a/Samples/TouchKeyboard/cpp/SampleConfiguration.cpp b/archived/TouchKeyboard/cpp/SampleConfiguration.cpp
similarity index 100%
rename from Samples/TouchKeyboard/cpp/SampleConfiguration.cpp
rename to archived/TouchKeyboard/cpp/SampleConfiguration.cpp
diff --git a/Samples/TouchKeyboard/cpp/SampleConfiguration.h b/archived/TouchKeyboard/cpp/SampleConfiguration.h
similarity index 100%
rename from Samples/TouchKeyboard/cpp/SampleConfiguration.h
rename to archived/TouchKeyboard/cpp/SampleConfiguration.h
diff --git a/archived/TouchKeyboard/cpp/Scenario1_Launch.xaml b/archived/TouchKeyboard/cpp/Scenario1_Launch.xaml
new file mode 100644
index 0000000000..d5a8e5f5bd
--- /dev/null
+++ b/archived/TouchKeyboard/cpp/Scenario1_Launch.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+ The touch keyboard displays
+ when touch or pen is used to set focus on a XAML text control
+ (such as TextBox, RichTextBox, and PasswordBox)
+ or a control derived from a XAML text control,
+ subject to the note below.
+
+
+
+
+
+ The keyboard hides when you tap the button.
+
+
+
+
+
+
+
+ The touch keyboard displays automatically when
+ 1. A hardware keyboard is not active, and
+ 2. Either of the following is true:
+
+
+ 2a. Tablet mode is turned on, or
+ 2b. "Show the touch keyboard when not in tablet mode
+ and there's no keyboard attached" is enabled in
+ Settings → Devices → Typing .
+
+
+
+
diff --git a/Samples/TouchKeyboard/cpp/Scenario1_Launch.xaml.cpp b/archived/TouchKeyboard/cpp/Scenario1_Launch.xaml.cpp
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario1_Launch.xaml.cpp
rename to archived/TouchKeyboard/cpp/Scenario1_Launch.xaml.cpp
diff --git a/Samples/TouchKeyboard/cpp/Scenario1_Launch.xaml.h b/archived/TouchKeyboard/cpp/Scenario1_Launch.xaml.h
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario1_Launch.xaml.h
rename to archived/TouchKeyboard/cpp/Scenario1_Launch.xaml.h
diff --git a/Samples/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.cpp b/archived/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.cpp
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.cpp
rename to archived/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.cpp
diff --git a/Samples/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.h b/archived/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.h
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.h
rename to archived/TouchKeyboard/cpp/Scenario2_DoNotAutoInvoke.xaml.h
diff --git a/Samples/TouchKeyboard/Shared/Scenario2_DoNotAutoInvoke.xaml b/archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml
similarity index 66%
rename from Samples/TouchKeyboard/Shared/Scenario2_DoNotAutoInvoke.xaml
rename to archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml
index fbb25427c7..d46a3742c9 100644
--- a/Samples/TouchKeyboard/Shared/Scenario2_DoNotAutoInvoke.xaml
+++ b/archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml
@@ -1,4 +1,4 @@
-
@@ -23,13 +24,17 @@
- Set InputPaneDisplayPolicy to Manual to disable the touch keyboard
- until manually invoked by the user.
- To add the Touch keyboard button to the taskbar, right-click on the taskbar
- and select the "Show touch keyboard button" item in the context menu.
+ The Showing and Hiding events are raised when the touch keyboard is shown or hidden.
- Prevent touch keyboard from showing on focus change
-
+
+
+ Last event:
+
+
+
+
+
+
See the note in scenario 1 for the rules regarding the touch keyboard.
diff --git a/Samples/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.cpp b/archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.cpp
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.cpp
rename to archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.cpp
diff --git a/Samples/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.h b/archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.h
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.h
rename to archived/TouchKeyboard/cpp/Scenario2_ShowHideEvents.xaml.h
diff --git a/archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml b/archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml
new file mode 100644
index 0000000000..b094294cf2
--- /dev/null
+++ b/archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This scenario hides the touch keyboard with TryHide() when you press Enter,
+ so that it won't cover the results below the text box.
+ When the results are cleared, it shows the touch keyboard again.
+
+
+ See the note in scenario 1 for the rules regarding the touch keyboard.
+
+
+
+
+
+
+
+
+
diff --git a/Samples/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.cpp b/archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.cpp
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.cpp
rename to archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.cpp
diff --git a/Samples/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.h b/archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.h
similarity index 100%
rename from Samples/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.h
rename to archived/TouchKeyboard/cpp/Scenario3_ShowHideMethods.xaml.h
diff --git a/Samples/TouchKeyboard/cpp/TouchKeyboard.sln b/archived/TouchKeyboard/cpp/TouchKeyboard.sln
similarity index 100%
rename from Samples/TouchKeyboard/cpp/TouchKeyboard.sln
rename to archived/TouchKeyboard/cpp/TouchKeyboard.sln
diff --git a/Samples/TouchKeyboard/cpp/TouchKeyboard.vcxproj b/archived/TouchKeyboard/cpp/TouchKeyboard.vcxproj
similarity index 100%
rename from Samples/TouchKeyboard/cpp/TouchKeyboard.vcxproj
rename to archived/TouchKeyboard/cpp/TouchKeyboard.vcxproj
diff --git a/Samples/TouchKeyboard/cpp/TouchKeyboard.vcxproj.filters b/archived/TouchKeyboard/cpp/TouchKeyboard.vcxproj.filters
similarity index 100%
rename from Samples/TouchKeyboard/cpp/TouchKeyboard.vcxproj.filters
rename to archived/TouchKeyboard/cpp/TouchKeyboard.vcxproj.filters
diff --git a/Samples/UserCertificateStore/cpp/pch.cpp b/archived/TouchKeyboard/cpp/pch.cpp
similarity index 100%
rename from Samples/UserCertificateStore/cpp/pch.cpp
rename to archived/TouchKeyboard/cpp/pch.cpp
diff --git a/Samples/UserCertificateStore/cpp/pch.h b/archived/TouchKeyboard/cpp/pch.h
similarity index 100%
rename from Samples/UserCertificateStore/cpp/pch.h
rename to archived/TouchKeyboard/cpp/pch.h
diff --git a/archived/UserCertificateStore/README.md b/archived/UserCertificateStore/README.md
index a828ae4fe9..89708ad20d 100644
--- a/archived/UserCertificateStore/README.md
+++ b/archived/UserCertificateStore/README.md
@@ -2,6 +2,8 @@
topic: sample
languages:
- js
+- cpp
+- cppcx
products:
- windows
- windows-uwp
@@ -44,11 +46,9 @@ the app must have the sharedUserCertificate capability.
## System requirements
-**Client:** Windows 10 build 14295
+**Client:** Windows 10 Version 1607
-**Server:** Windows Server 2016 Technical Preview
-
-**Phone:** Windows 10 build 14295
+**Server:** Windows Server 2016
## Build the sample
diff --git a/Samples/UserCertificateStore/cpp/Package.appxmanifest b/archived/UserCertificateStore/cpp/Package.appxmanifest
similarity index 100%
rename from Samples/UserCertificateStore/cpp/Package.appxmanifest
rename to archived/UserCertificateStore/cpp/Package.appxmanifest
diff --git a/Samples/UserCertificateStore/cpp/SampleConfiguration.cpp b/archived/UserCertificateStore/cpp/SampleConfiguration.cpp
similarity index 100%
rename from Samples/UserCertificateStore/cpp/SampleConfiguration.cpp
rename to archived/UserCertificateStore/cpp/SampleConfiguration.cpp
diff --git a/Samples/UserCertificateStore/cpp/SampleConfiguration.h b/archived/UserCertificateStore/cpp/SampleConfiguration.h
similarity index 100%
rename from Samples/UserCertificateStore/cpp/SampleConfiguration.h
rename to archived/UserCertificateStore/cpp/SampleConfiguration.h
diff --git a/archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml b/archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml
new file mode 100644
index 0000000000..06ab017564
--- /dev/null
+++ b/archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.cpp b/archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.cpp
similarity index 100%
rename from Samples/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.cpp
rename to archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.cpp
diff --git a/Samples/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.h b/archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.h
similarity index 100%
rename from Samples/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.h
rename to archived/UserCertificateStore/cpp/Scenario1_MoveCertificate.xaml.h
diff --git a/Samples/UserCertificateStore/cpp/UserCertificateStore.sln b/archived/UserCertificateStore/cpp/UserCertificateStore.sln
similarity index 100%
rename from Samples/UserCertificateStore/cpp/UserCertificateStore.sln
rename to archived/UserCertificateStore/cpp/UserCertificateStore.sln
diff --git a/Samples/UserCertificateStore/cpp/UserCertificateStore.vcxproj b/archived/UserCertificateStore/cpp/UserCertificateStore.vcxproj
similarity index 97%
rename from Samples/UserCertificateStore/cpp/UserCertificateStore.vcxproj
rename to archived/UserCertificateStore/cpp/UserCertificateStore.vcxproj
index a1e7deab95..fac87498bb 100644
--- a/Samples/UserCertificateStore/cpp/UserCertificateStore.vcxproj
+++ b/archived/UserCertificateStore/cpp/UserCertificateStore.vcxproj
@@ -139,7 +139,7 @@
- ..\shared\Scenario1_MoveCertificate.xaml
+ Scenario1_MoveCertificate.xaml
@@ -149,7 +149,7 @@
Designer
-
+
Styles\Styles.xaml
@@ -176,7 +176,7 @@
- ..\shared\Scenario1_MoveCertificate.xaml
+ Scenario1_MoveCertificate.xaml
diff --git a/Samples/UserCertificateStore/cpp/UserCertificateStore.vcxproj.filters b/archived/UserCertificateStore/cpp/UserCertificateStore.vcxproj.filters
similarity index 97%
rename from Samples/UserCertificateStore/cpp/UserCertificateStore.vcxproj.filters
rename to archived/UserCertificateStore/cpp/UserCertificateStore.vcxproj.filters
index 3bcf98c2e6..efe85cd1af 100644
--- a/Samples/UserCertificateStore/cpp/UserCertificateStore.vcxproj.filters
+++ b/archived/UserCertificateStore/cpp/UserCertificateStore.vcxproj.filters
@@ -34,7 +34,7 @@
Styles
-
+
diff --git a/archived/UserCertificateStore/cpp/pch.cpp b/archived/UserCertificateStore/cpp/pch.cpp
new file mode 100644
index 0000000000..ade821753a
--- /dev/null
+++ b/archived/UserCertificateStore/cpp/pch.cpp
@@ -0,0 +1,5 @@
+//
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/archived/UserCertificateStore/cpp/pch.h b/archived/UserCertificateStore/cpp/pch.h
new file mode 100644
index 0000000000..1dcc72eba4
--- /dev/null
+++ b/archived/UserCertificateStore/cpp/pch.h
@@ -0,0 +1,10 @@
+//
+// Header for standard system include files.
+//
+
+#pragma once
+
+#include
+#include
+
+#include "App.xaml.h"
diff --git a/Samples/VoIP/README.md b/archived/VoIP/README.md
similarity index 99%
rename from Samples/VoIP/README.md
rename to archived/VoIP/README.md
index 9b884d1ebf..843e258a89 100644
--- a/Samples/VoIP/README.md
+++ b/archived/VoIP/README.md
@@ -1,5 +1,5 @@
---
-page_type: sample
+topic: sample
languages:
- csharp
products:
diff --git a/Samples/VoIP/cs/Voip.sln b/archived/VoIP/cs/Voip.sln
similarity index 100%
rename from Samples/VoIP/cs/Voip.sln
rename to archived/VoIP/cs/Voip.sln
diff --git a/Samples/VoIP/cs/Voip/App.xaml b/archived/VoIP/cs/Voip/App.xaml
similarity index 100%
rename from Samples/VoIP/cs/Voip/App.xaml
rename to archived/VoIP/cs/Voip/App.xaml
diff --git a/Samples/VoIP/cs/Voip/App.xaml.cs b/archived/VoIP/cs/Voip/App.xaml.cs
similarity index 100%
rename from Samples/VoIP/cs/Voip/App.xaml.cs
rename to archived/VoIP/cs/Voip/App.xaml.cs
diff --git a/Samples/VoIP/cs/Voip/Helpers/AppServiceHelper.cs b/archived/VoIP/cs/Voip/Helpers/AppServiceHelper.cs
similarity index 100%
rename from Samples/VoIP/cs/Voip/Helpers/AppServiceHelper.cs
rename to archived/VoIP/cs/Voip/Helpers/AppServiceHelper.cs
diff --git a/Samples/VoIP/cs/Voip/Helpers/VoipCallHelper.cs b/archived/VoIP/cs/Voip/Helpers/VoipCallHelper.cs
similarity index 100%
rename from Samples/VoIP/cs/Voip/Helpers/VoipCallHelper.cs
rename to archived/VoIP/cs/Voip/Helpers/VoipCallHelper.cs
diff --git a/Samples/VoIP/cs/Voip/MainPage.xaml b/archived/VoIP/cs/Voip/MainPage.xaml
similarity index 100%
rename from Samples/VoIP/cs/Voip/MainPage.xaml
rename to archived/VoIP/cs/Voip/MainPage.xaml
diff --git a/Samples/VoIP/cs/Voip/MainPage.xaml.cs b/archived/VoIP/cs/Voip/MainPage.xaml.cs
similarity index 100%
rename from Samples/VoIP/cs/Voip/MainPage.xaml.cs
rename to archived/VoIP/cs/Voip/MainPage.xaml.cs
diff --git a/Samples/VoIP/cs/Voip/Package.appxmanifest b/archived/VoIP/cs/Voip/Package.appxmanifest
similarity index 100%
rename from Samples/VoIP/cs/Voip/Package.appxmanifest
rename to archived/VoIP/cs/Voip/Package.appxmanifest
diff --git a/Samples/VoIP/cs/Voip/Voip.csproj b/archived/VoIP/cs/Voip/Voip.csproj
similarity index 100%
rename from Samples/VoIP/cs/Voip/Voip.csproj
rename to archived/VoIP/cs/Voip/Voip.csproj
diff --git a/Samples/VoIP/cs/VoipBackEnd/ApiLock.cpp b/archived/VoIP/cs/VoipBackEnd/ApiLock.cpp
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/ApiLock.cpp
rename to archived/VoIP/cs/VoipBackEnd/ApiLock.cpp
diff --git a/Samples/VoIP/cs/VoipBackEnd/ApiLock.h b/archived/VoIP/cs/VoipBackEnd/ApiLock.h
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/ApiLock.h
rename to archived/VoIP/cs/VoipBackEnd/ApiLock.h
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndAudio.cpp b/archived/VoIP/cs/VoipBackEnd/BackEndAudio.cpp
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndAudio.cpp
rename to archived/VoIP/cs/VoipBackEnd/BackEndAudio.cpp
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndAudio.h b/archived/VoIP/cs/VoipBackEnd/BackEndAudio.h
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndAudio.h
rename to archived/VoIP/cs/VoipBackEnd/BackEndAudio.h
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.cpp b/archived/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.cpp
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.cpp
rename to archived/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.cpp
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.h b/archived/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.h
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.h
rename to archived/VoIP/cs/VoipBackEnd/BackEndAudioHelpers.h
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndNativeBuffer.h b/archived/VoIP/cs/VoipBackEnd/BackEndNativeBuffer.h
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndNativeBuffer.h
rename to archived/VoIP/cs/VoipBackEnd/BackEndNativeBuffer.h
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndTransport.cpp b/archived/VoIP/cs/VoipBackEnd/BackEndTransport.cpp
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndTransport.cpp
rename to archived/VoIP/cs/VoipBackEnd/BackEndTransport.cpp
diff --git a/Samples/VoIP/cs/VoipBackEnd/BackEndTransport.h b/archived/VoIP/cs/VoipBackEnd/BackEndTransport.h
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/BackEndTransport.h
rename to archived/VoIP/cs/VoipBackEnd/BackEndTransport.h
diff --git a/Samples/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj b/archived/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj
rename to archived/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj
diff --git a/Samples/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj.filters b/archived/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj.filters
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj.filters
rename to archived/VoIP/cs/VoipBackEnd/VoipBackEnd.vcxproj.filters
diff --git a/archived/VoIP/cs/VoipBackEnd/pch.cpp b/archived/VoIP/cs/VoipBackEnd/pch.cpp
new file mode 100644
index 0000000000..dc586a230a
--- /dev/null
+++ b/archived/VoIP/cs/VoipBackEnd/pch.cpp
@@ -0,0 +1,11 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+#include "pch.h"
diff --git a/Samples/VoIP/cs/VoipBackEnd/pch.h b/archived/VoIP/cs/VoipBackEnd/pch.h
similarity index 100%
rename from Samples/VoIP/cs/VoipBackEnd/pch.h
rename to archived/VoIP/cs/VoipBackEnd/pch.h
diff --git a/Samples/VoIP/cs/VoipHost/VoipHost.cpp b/archived/VoIP/cs/VoipHost/VoipHost.cpp
similarity index 100%
rename from Samples/VoIP/cs/VoipHost/VoipHost.cpp
rename to archived/VoIP/cs/VoipHost/VoipHost.cpp
diff --git a/Samples/VoIP/cs/VoipHost/VoipHost.vcxproj b/archived/VoIP/cs/VoipHost/VoipHost.vcxproj
similarity index 100%
rename from Samples/VoIP/cs/VoipHost/VoipHost.vcxproj
rename to archived/VoIP/cs/VoipHost/VoipHost.vcxproj
diff --git a/Samples/VoIP/cs/VoipHost/VoipHost.vcxproj.filters b/archived/VoIP/cs/VoipHost/VoipHost.vcxproj.filters
similarity index 100%
rename from Samples/VoIP/cs/VoipHost/VoipHost.vcxproj.filters
rename to archived/VoIP/cs/VoipHost/VoipHost.vcxproj.filters
diff --git a/Samples/VoIP/cs/VoipTasks/AppService.cs b/archived/VoIP/cs/VoipTasks/AppService.cs
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/AppService.cs
rename to archived/VoIP/cs/VoipTasks/AppService.cs
diff --git a/Samples/VoIP/cs/VoipTasks/BackgroundOperations/BackgroundOperations.cs b/archived/VoIP/cs/VoipTasks/BackgroundOperations/BackgroundOperations.cs
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/BackgroundOperations/BackgroundOperations.cs
rename to archived/VoIP/cs/VoipTasks/BackgroundOperations/BackgroundOperations.cs
diff --git a/Samples/VoIP/cs/VoipTasks/CallRtcTask.cs b/archived/VoIP/cs/VoipTasks/CallRtcTask.cs
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/CallRtcTask.cs
rename to archived/VoIP/cs/VoipTasks/CallRtcTask.cs
diff --git a/Samples/VoIP/cs/VoipTasks/Helpers/Current.cs b/archived/VoIP/cs/VoipTasks/Helpers/Current.cs
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/Helpers/Current.cs
rename to archived/VoIP/cs/VoipTasks/Helpers/Current.cs
diff --git a/Samples/VoIP/cs/VoipTasks/Helpers/VccCallHelper.cs b/archived/VoIP/cs/VoipTasks/Helpers/VccCallHelper.cs
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/Helpers/VccCallHelper.cs
rename to archived/VoIP/cs/VoipTasks/Helpers/VccCallHelper.cs
diff --git a/Samples/VoIP/cs/VoipTasks/Properties/AssemblyInfo.cs b/archived/VoIP/cs/VoipTasks/Properties/AssemblyInfo.cs
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/Properties/AssemblyInfo.cs
rename to archived/VoIP/cs/VoipTasks/Properties/AssemblyInfo.cs
diff --git a/Samples/VoIP/cs/VoipTasks/VoipTasks.csproj b/archived/VoIP/cs/VoipTasks/VoipTasks.csproj
similarity index 100%
rename from Samples/VoIP/cs/VoipTasks/VoipTasks.csproj
rename to archived/VoIP/cs/VoipTasks/VoipTasks.csproj