Merge pull request #217 from Microsoft/develop

Develop merge
This commit is contained in:
adiviness 2016-10-20 10:21:06 -07:00 коммит произвёл GitHub
Родитель 1707d96539 751451d8dd
Коммит cfa49c33a7
25 изменённых файлов: 480 добавлений и 272 удалений

Просмотреть файл

@ -210,14 +210,14 @@
<ItemGroup> <ItemGroup>
<PRIResource Include="Resources.resw" /> <PRIResource Include="Resources.resw" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\..\..\winsdkfb\winsdkfb_testing_key.pfx" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\winsdkfb\winsdkfb_uwp\winsdkfb_uwp\winsdkfb_uwp.vcxproj"> <ProjectReference Include="..\..\..\winsdkfb\winsdkfb_uwp\winsdkfb_uwp\winsdkfb_uwp.vcxproj">
<Project>{973a943b-ff77-4267-8f30-f5fe2b7f5583}</Project> <Project>{973a943b-ff77-4267-8f30-f5fe2b7f5583}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\..\..\winsdkfb\winsdkfb_testing_key.pfx" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" /> <ImportGroup Label="ExtensionTargets" />
</Project> </Project>

Просмотреть файл

@ -34,7 +34,6 @@
<ClCompile Include="FBPageBindable.cpp" /> <ClCompile Include="FBPageBindable.cpp" />
<ClCompile Include="UserInfo.xaml.cpp" /> <ClCompile Include="UserInfo.xaml.cpp" />
<ClCompile Include="UserLikes.xaml.cpp" /> <ClCompile Include="UserLikes.xaml.cpp" />
<ClCompile Include="OptionsPage.xaml.cpp" />
<ClCompile Include="Dialogs.xaml.cpp" /> <ClCompile Include="Dialogs.xaml.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -47,7 +46,6 @@
<ClInclude Include="FBPageBindable.h" /> <ClInclude Include="FBPageBindable.h" />
<ClInclude Include="UserInfo.xaml.h" /> <ClInclude Include="UserInfo.xaml.h" />
<ClInclude Include="UserLikes.xaml.h" /> <ClInclude Include="UserLikes.xaml.h" />
<ClInclude Include="OptionsPage.xaml.h" />
<ClInclude Include="Dialogs.xaml.h" /> <ClInclude Include="Dialogs.xaml.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Просмотреть файл

@ -114,13 +114,18 @@
<None Include="..\winsdkfb_testing_key.pfx"> <None Include="..\winsdkfb_testing_key.pfx">
<Link>winsdkfb_testing_key.pfx</Link> <Link>winsdkfb_testing_key.pfx</Link>
</None> </None>
<None Include="data.json" />
<None Include="FBCSObjectImplementation.ttinclude" /> <None Include="FBCSObjectImplementation.ttinclude" />
<None Include="FBPhoto.tt" /> <None Include="FBPhoto.tt" />
<None Include="FBObject.tt" /> <None Include="FBObject.tt" />
<None Include="FBSuccess.tt" /> <None Include="FBSuccess.tt" />
<None Include="FBTestUser.tt" /> <None Include="FBTestUser.tt" />
<None Include="packages.config" /> <None Include="packages.config" />
<Content Include="TestData\testJsonPropertySet.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestData\testJsonPropertySetNoBuiltInFields.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="Utility.ttinclude" /> <None Include="Utility.ttinclude" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Просмотреть файл

@ -29,7 +29,7 @@ namespace FBWinStoreCsTests
{ {
public String ResponseData; public String ResponseData;
public IAsyncOperation<string> DeleteTaskAsync(string path, PropertySet parameters) public IAsyncOperation<string> DeleteTaskAsync(string path, IReadOnlyDictionary<String, Object> parameters)
{ {
return Task.Run(() => return Task.Run(() =>
{ {
@ -37,7 +37,7 @@ namespace FBWinStoreCsTests
}).AsAsyncOperation<string>(); }).AsAsyncOperation<string>();
} }
public IAsyncOperation<string> GetTaskAsync(string path, PropertySet parameters) public IAsyncOperation<string> GetTaskAsync(string path, IReadOnlyDictionary<String, Object> parameters)
{ {
return Task.Run(() => return Task.Run(() =>
{ {
@ -45,12 +45,12 @@ namespace FBWinStoreCsTests
}).AsAsyncOperation<string>(); }).AsAsyncOperation<string>();
} }
public string ParametersToQueryString(PropertySet Parameters) public string ParametersToQueryString(IReadOnlyDictionary<String, Object> Parameters)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public IAsyncOperation<string> PostTaskAsync(string path, PropertySet parameters) public IAsyncOperation<string> PostTaskAsync(string path, IReadOnlyDictionary<String, Object> parameters)
{ {
return Task.Run(() => return Task.Run(() =>
{ {

Просмотреть файл

@ -0,0 +1,11 @@
{
"name": "test_user",
"test_boolean": false,
"test_num": 4,
"test_string": "hello_world",
"test_array": [ 2, 3, 5, 7, 11 ],
"test_object": {
"a": "b",
"c": "d"
}
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"test_boolean": false,
"test_num": 4,
"test_string": "hello_world",
"test_array": [ 2, 3, 5, 7, 11 ],
"test_object": {
"a": "b",
"c": "d"
}
}

Просмотреть файл

@ -15,6 +15,7 @@
//****************************************************************************** //******************************************************************************
using System; using System;
using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -700,5 +701,49 @@ namespace FBWinStoreCsTests
Assert.IsFalse(likes.HasPrevious); Assert.IsFalse(likes.HasPrevious);
// test with next but no previous // test with next but no previous
} }
[TestMethod]
public async Task testJsonPropertySet()
{
StorageFolder installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder jsonFolder = await installedLocation.GetFolderAsync("TestData");
StorageFile jsonTestFile = await jsonFolder.GetFileAsync("testJsonPropertySet.json");
string text = await FileIO.ReadTextAsync(jsonTestFile);
FBUser testUser = (FBUser)FBUser.FromJson(text);
// member variable
Assert.AreEqual(testUser.Name, "test_user");
Assert.IsFalse(testUser.Fields.ContainsKey("name"));
// boolean field
Assert.IsTrue(testUser.Fields.ContainsKey("test_boolean"));
Assert.AreEqual(testUser.Fields["test_boolean"], "false");
// num field
Assert.IsTrue(testUser.Fields.ContainsKey("test_num"));
Assert.AreEqual(testUser.Fields["test_num"], "4");
// string field
Assert.IsTrue(testUser.Fields.ContainsKey("test_string"));
Assert.AreEqual(testUser.Fields["test_string"], "hello_world");
// array field
Assert.IsTrue(testUser.Fields.ContainsKey("test_array"));
Assert.AreEqual(testUser.Fields["test_array"], "[2,3,5,7,11]");
// object field
Assert.IsTrue(testUser.Fields.ContainsKey("test_object"));
Assert.AreEqual(testUser.Fields["test_object"], @"{""a"":""b"",""c"":""d""}");
}
[TestMethod]
public async Task testJsonPropertySetNoBuiltInFields()
{
StorageFolder installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder jsonFolder = await installedLocation.GetFolderAsync("TestData");
StorageFile jsonTestFile = await jsonFolder.GetFileAsync("testJsonPropertySetNoBuiltInFields.json");
string text = await FileIO.ReadTextAsync(jsonTestFile);
FBUser testUser = (FBUser)FBUser.FromJson(text);
Assert.AreNotEqual(testUser, null);
}
} }
} }

Просмотреть файл

Просмотреть файл

@ -89,6 +89,10 @@ namespace winsdkfb
Platform::String^ JsonText Platform::String^ JsonText
); );
property Windows::Foundation::Collections::PropertySet^ Fields
{
Windows::Foundation::Collections::PropertySet^ get();
}
<# <#
foreach (XmlNode child in rootNode.SelectNodes("property")) foreach (XmlNode child in rootNode.SelectNodes("property"))
@ -129,6 +133,7 @@ namespace winsdkfb
<# <#
} }
#> #>
Windows::Foundation::Collections::PropertySet^ _fields;
}; };
} }
} }

Просмотреть файл

@ -38,7 +38,7 @@ using namespace winsdkfb::Graph;
using namespace Platform; using namespace Platform;
using namespace Windows::Data::Json; using namespace Windows::Data::Json;
using namespace Windows::Foundation::Collections; using namespace Windows::Foundation::Collections;
<# <#
if (bindable) if (bindable)
{ {
#> #>
@ -86,9 +86,13 @@ using namespace Windows::UI::Xaml::Data;
} }
#> #>
{ {
; _fields = ref new PropertySet();
} }
PropertySet^ <#= className #>::Fields::get()
{
return _fields;
}
<# <#
for (int i = 0; i < props.Count; i++) for (int i = 0; i < props.Count; i++)
{ {
@ -118,7 +122,7 @@ void <#= className #>::<#= propName #>::set(<#= rtType #> value)
} }
#> #>
Object^ <#= className #>::FromJson( Object^ <#= className #>::FromJson(
String^ JsonText String^ JsonText
) )
{ {
<#= className #>^ result = ref new <#= className #>; <#= className #>^ result = ref new <#= className #>;
@ -178,11 +182,38 @@ Object^ <#= className #>::FromJson(
<# <#
} }
#> #>
else
{
String^ value = nullptr;
switch (it->Current->Value->ValueType)
{
case JsonValueType::Boolean:
value = it->Current->Value->GetBoolean().ToString();
break;
case JsonValueType::Number:
value = it->Current->Value->GetNumber().ToString();
break;
case JsonValueType::String:
value = it->Current->Value->GetString();
break;
case JsonValueType::Array:
case JsonValueType::Object:
value = it->Current->Value->Stringify();
break;
}
if (value)
{
result->_fields->Insert(key, value);
found++;
}
}
} }
if (!found) if (!found)
{ {
// No field names matched any known properties for this class. // No field names matched any known properties for this class.
// Even if it *is* an object of our type, it's not useful. // Even if it *is* an object of our type, it's not useful.
result = nullptr; result = nullptr;
} }
@ -190,7 +221,7 @@ Object^ <#= className #>::FromJson(
} }
return result; return result;
} }
<# <#
if (bindable) if (bindable)
{ {
#> #>
@ -200,7 +231,7 @@ void <#= className #>::NotifyPropertyChanged(
) )
{ {
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
Windows::UI::Core::CoreDispatcherPriority::Normal, Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([this, prop]() ref new Windows::UI::Core::DispatchedHandler([this, prop]()
{ {
PropertyChangedEventArgs^ args = ref new PropertyChangedEventArgs(prop); PropertyChangedEventArgs^ args = ref new PropertyChangedEventArgs(prop);

Просмотреть файл

@ -146,13 +146,13 @@ Windows::Foundation::IAsyncOperation<FBResult^>^ FBSingleValue::MakeHttpRequest(
switch (httpMethod) switch (httpMethod)
{ {
case HttpMethod::Get: case HttpMethod::Get:
innerTask = create_task(HttpManager::Instance->GetTaskAsync(_request, _parameters)); innerTask = create_task(HttpManager::Instance->GetTaskAsync(_request, _parameters->GetView()));
break; break;
case HttpMethod::Post: case HttpMethod::Post:
innerTask = create_task(HttpManager::Instance->PostTaskAsync(_request, _parameters)); innerTask = create_task(HttpManager::Instance->PostTaskAsync(_request, _parameters->GetView()));
break; break;
case HttpMethod::Delete: case HttpMethod::Delete:
innerTask = create_task(HttpManager::Instance->DeleteTaskAsync(_request, _parameters)); innerTask = create_task(HttpManager::Instance->DeleteTaskAsync(_request, _parameters->GetView()));
break; break;
default: default:
OutputDebugString(L"FBSingleValue::MakeHttpRequest recieved unknown HttpMethod value\n"); OutputDebugString(L"FBSingleValue::MakeHttpRequest recieved unknown HttpMethod value\n");

Просмотреть файл

@ -23,6 +23,7 @@
#include "HttpMethod.h" #include "HttpMethod.h"
#include "JsonClassFactory.h" #include "JsonClassFactory.h"
#include "SDKMessage.h" #include "SDKMessage.h"
#include "GraphUriBuilder.h"
using namespace concurrency; using namespace concurrency;
using namespace Platform; using namespace Platform;
@ -96,25 +97,26 @@ PropertySet^ FBClient::ToDictionary(PropertySet^ parameters, PropertySet^ mediaO
IAsyncOperation<String^>^ FBClient::GetTaskAsync( IAsyncOperation<String^>^ FBClient::GetTaskAsync(
String^ path, String^ path,
PropertySet^ parameters IMapView<String^, Object^>^ parameters
) )
{ {
PropertySet^ modifiableParams = MapViewToPropertySet(parameters);
IAsyncOperation<String^>^ myTask = create_async([=]() IAsyncOperation<String^>^ myTask = create_async([=]()
{ {
Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Get, path, Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Get, path,
parameters, nullptr); modifiableParams);
return FBClient::GetTaskInternalAsync(uri) return FBClient::GetTaskInternalAsync(uri)
.then([=](String^ Response) .then([=](String^ Response)
{ {
task<String^> result; task<String^> result;
if (FBClient::IsOAuthErrorResponse(Response)) if (FBClient::IsOAuthErrorResponse(Response))
{ {
result = create_task([=]() result = create_task([=]()
{ {
FBSession^ sess = FBSession::ActiveSession; FBSession^ sess = FBSession::ActiveSession;
return FBSession::ActiveSession->TryRefreshAccessToken(); return FBSession::ActiveSession->TryRefreshAccessToken();
}) })
.then([=](FBResult^ Result) .then([=](FBResult^ Result)
{ {
@ -186,7 +188,7 @@ IAsyncOperation<String^>^ FBClient::SimplePostAsync(
return create_async([=]() return create_async([=]()
{ {
Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Post, path, Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Post, path,
parameters, nullptr); parameters);
return FBClient::SimplePostInternalAsync(uri) return FBClient::SimplePostInternalAsync(uri)
.then([=](String^ Response) .then([=](String^ Response)
@ -198,7 +200,7 @@ IAsyncOperation<String^>^ FBClient::SimplePostAsync(
result = create_task([=]() result = create_task([=]()
{ {
FBSession^ sess = FBSession::ActiveSession; FBSession^ sess = FBSession::ActiveSession;
return FBSession::ActiveSession->TryRefreshAccessToken(); return FBSession::ActiveSession->TryRefreshAccessToken();
}) })
.then([=](FBResult^ Result) .then([=](FBResult^ Result)
{ {
@ -266,7 +268,7 @@ IAsyncOperation<String^>^ FBClient::MultipartPostAsync(
return create_async([=]() return create_async([=]()
{ {
Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Post, path, Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Post, path,
parameters, nullptr); parameters);
return FBClient::MultipartPostInternalAsync(uri, streams) return FBClient::MultipartPostInternalAsync(uri, streams)
.then([=](String^ Response) .then([=](String^ Response)
@ -278,7 +280,7 @@ IAsyncOperation<String^>^ FBClient::MultipartPostAsync(
result = create_task([=]() result = create_task([=]()
{ {
FBSession^ sess = FBSession::ActiveSession; FBSession^ sess = FBSession::ActiveSession;
return FBSession::ActiveSession->TryRefreshAccessToken(); return FBSession::ActiveSession->TryRefreshAccessToken();
}) })
.then([=](FBResult^ Result) .then([=](FBResult^ Result)
{ {
@ -318,32 +320,33 @@ task<String^> FBClient::MultipartPostInternalAsync(
IAsyncOperation<String^>^ FBClient::PostTaskAsync( IAsyncOperation<String^>^ FBClient::PostTaskAsync(
String^ path, String^ path,
PropertySet^ parameters IMapView<String^, Object^>^ parameters
) )
{ {
PropertySet^ modifiableParams = MapViewToPropertySet(parameters);
IAsyncOperation<String^>^ result = nullptr; IAsyncOperation<String^>^ result = nullptr;
PropertySet^ streams = GetStreamsToUpload(parameters); PropertySet^ streams = GetStreamsToUpload(modifiableParams);
if (streams) if (streams)
{ {
result = FBClient::MultipartPostAsync(path, parameters, streams); result = FBClient::MultipartPostAsync(path, modifiableParams, streams);
} }
else else
{ {
result = FBClient::SimplePostAsync(path, parameters); result = FBClient::SimplePostAsync(path, modifiableParams);
} }
return result; return result;
} }
Windows::Foundation::IAsyncOperation<String^>^ FBClient::DeleteTaskAsync( Windows::Foundation::IAsyncOperation<String^>^ FBClient::DeleteTaskAsync(
String^ path, String^ path,
PropertySet^ parameters IMapView<String^, Object^>^ parameters
) )
{ {
PropertySet^ modifiableParams = MapViewToPropertySet(parameters);
return create_async([=]() return create_async([=]()
{ {
Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Delete, path, Uri^ uri = FBClient::PrepareRequestUri(HttpMethod::Delete, path,
parameters, nullptr); modifiableParams);
return FBClient::DeleteTaskInternalAsync(uri) return FBClient::DeleteTaskInternalAsync(uri)
.then([=](String^ Response) .then([=](String^ Response)
@ -355,7 +358,7 @@ Windows::Foundation::IAsyncOperation<String^>^ FBClient::DeleteTaskAsync(
result = create_task([=]() result = create_task([=]()
{ {
FBSession^ sess = FBSession::ActiveSession; FBSession^ sess = FBSession::ActiveSession;
return FBSession::ActiveSession->TryRefreshAccessToken(); return FBSession::ActiveSession->TryRefreshAccessToken();
}) })
.then([=](FBResult^ Result) .then([=](FBResult^ Result)
{ {
@ -390,34 +393,37 @@ task<String^> FBClient::DeleteTaskInternalAsync(
} }
Uri^ FBClient::PrepareRequestUri( Uri^ FBClient::PrepareRequestUri(
winsdkfb::HttpMethod httpMethod, winsdkfb::HttpMethod httpMethod,
String^ path, String^ path,
PropertySet^ parameters, PropertySet^ parameters
Windows::Storage::Streams::IRandomAccessStream^ input
) )
{ {
FBSession^ sess = FBSession::ActiveSession; FBSession^ sess = FBSession::ActiveSession;
GraphUriBuilder^ uriBuilder = ref new GraphUriBuilder(path);
// Setup datawriter for the InMemoryRandomAccessStream if (parameters == nullptr)
DataWriter^ dataWriter = ref new DataWriter(input); {
dataWriter->UnicodeEncoding = UnicodeEncoding::Utf8; parameters = ref new PropertySet();
dataWriter->ByteOrder = ByteOrder::LittleEndian; }
PropertySet^ mediaObjects = ref new PropertySet(); PropertySet^ mediaObjects = ref new PropertySet();
PropertySet^ mediaStreams = ref new PropertySet(); PropertySet^ mediaStreams = ref new PropertySet();
PropertySet^ parametersWithoutMediaObjects = ToDictionary(parameters, mediaObjects, mediaStreams); PropertySet^ parametersWithoutMediaObjects = ToDictionary(parameters, mediaObjects, mediaStreams);
// ensure that media items are in valid states
ValidateMediaStreams(mediaStreams);
ValidateMediaObjects(mediaObjects);
if (parametersWithoutMediaObjects == nullptr) if (parametersWithoutMediaObjects == nullptr)
{ {
parametersWithoutMediaObjects = ref new PropertySet(); parametersWithoutMediaObjects = ref new PropertySet();
} }
if (!parametersWithoutMediaObjects->HasKey("access_token") && if (!parametersWithoutMediaObjects->HasKey("access_token") &&
(sess->AccessTokenData != nullptr) && (sess->AccessTokenData != nullptr) &&
(sess->AccessTokenData->AccessToken->Data() != nullptr) && (sess->AccessTokenData->AccessToken->Data() != nullptr) &&
(sess->AccessTokenData->AccessToken->Length() > 0)) (sess->AccessTokenData->AccessToken->Length() > 0))
{ {
parametersWithoutMediaObjects->Insert("access_token", parametersWithoutMediaObjects->Insert("access_token",
sess->AccessTokenData->AccessToken); sess->AccessTokenData->AccessToken);
} }
@ -426,211 +432,71 @@ Uri^ FBClient::PrepareRequestUri(
parametersWithoutMediaObjects->Insert("format", "json-strings"); parametersWithoutMediaObjects->Insert("format", "json-strings");
} }
String^ contentTypeHeader = MultiPartContentType;
String^ boundary = ref new String(MultiPartBoundary);
contentTypeHeader += "boundary=" + boundary + MultiPartNewLine;
long contentLength = -1;
String^ queryString = ref new String();
OutputDebugString(contentTypeHeader->Data());
SerializeParameters(parametersWithoutMediaObjects); SerializeParameters(parametersWithoutMediaObjects);
if (parametersWithoutMediaObjects->HasKey("access_token")) // Add remaining parameters to query string. Note that parameters that
// do not need to be uploaded as multipart, i.e. any which is are not
// binary data, are required to be in the query string, even for POST
// requests!
auto kvp = parametersWithoutMediaObjects->First();
while (kvp->HasCurrent)
{ {
// Add access_token to query string as the first parameter, for our own uriBuilder->AddQueryParam(kvp->Current->Key, static_cast<String^>(kvp->Current->Value));
// convenience. We could as easily add it in the while loop below, but kvp->MoveNext();
// putting at the beginning of the query string is helpful for }
// debugging, etc.
auto accessToken = dynamic_cast<String^>(
parametersWithoutMediaObjects->Lookup("access_token"));
if ((accessToken != nullptr) && (accessToken->Length() > 0) &&
(accessToken != "null"))
{
queryString += "access_token=" + Uri::EscapeComponent(accessToken);
}
// Remove the token before we loop through and add general parameters return uriBuilder->MakeUri();
parametersWithoutMediaObjects->Remove("access_token"); }
// Add remaining parameters to query string. Note that parameters that
// do not need to be uploaded as multipart, i.e. any which is are not
// binary data, are required to be in the query string, even for POST
// requests!
auto kvp = parametersWithoutMediaObjects->First();
while (kvp->HasCurrent)
{
String^ key = Uri::EscapeComponent(kvp->Current->Key);
String^ value = Uri::EscapeComponent(
dynamic_cast<String^>(kvp->Current->Value));
if (queryString->Length() > 0) void FBClient::ValidateMediaStreams(PropertySet^ mediaStreams)
{
if (mediaStreams->Size > 0)
{
IIterator<IKeyValuePair<String^, Object^>^>^ facebookMediaStream = mediaStreams->First();
while(facebookMediaStream->HasCurrent)
{
FBMediaStream^ mediaStream = dynamic_cast<FBMediaStream^>(facebookMediaStream->Current->Value);
if ((mediaStream->Stream == nullptr) ||
(mediaStream->Stream->ContentType == nullptr) ||
(mediaStream->FileName == nullptr) ||
(mediaStream->FileName->Length() == 0))
{ {
queryString += "&"; throw ref new InvalidArgumentException(AttachmentMustHavePropertiesSetError);
} }
queryString += key + L"=" + value; IRandomAccessStream^ stream = mediaStream->Stream;
if (stream == nullptr)
kvp->MoveNext();
}
if (mediaStreams->Size > 0)
{
IIterator<IKeyValuePair<String^, Object^>^>^ facebookMediaStream =
mediaStreams->First();
while(facebookMediaStream->HasCurrent)
{ {
String^ sbMediaStream = ref new String(); throw ref new InvalidArgumentException(AttachmentValueIsNull);
FBMediaStream^ mediaStream = }
dynamic_cast<FBMediaStream^>( facebookMediaStream->MoveNext();
facebookMediaStream->Current->Value); }
}
}
if ((mediaStream->Stream == nullptr) || void FBClient::ValidateMediaObjects(PropertySet^ mediaObjects)
(mediaStream->Stream->ContentType == nullptr) || {
(mediaStream->FileName == nullptr) || if (mediaObjects->Size > 0)
(mediaStream->FileName->Length() == 0)) {
{ IIterator<IKeyValuePair<String^, Object^>^>^ facebookMediaObject = mediaObjects->First();
throw ref new InvalidArgumentException(AttachmentMustHavePropertiesSetError); while (facebookMediaObject->HasCurrent)
} {
FBMediaObject^ mediaObject = dynamic_cast<FBMediaObject^>(facebookMediaObject->Current->Value);
sbMediaStream = MultiPartFormPrefix + boundary + if ((mediaObject->GetValue()== nullptr) ||
MultiPartNewLine + (mediaObject->ContentType == nullptr) ||
"Content-Disposition: form-data; name=\"" + (mediaObject->FileName == nullptr) ||
facebookMediaStream->Current->Key + "\"; filename=\"" + (mediaObject->FileName->Length() == 0))
mediaStream->FileName + "\"" + MultiPartNewLine + {
"Content-Type: " + mediaStream->Stream->ContentType + throw ref new InvalidArgumentException(AttachmentMustHavePropertiesSetError);
MultiPartNewLine + MultiPartNewLine;
OutputDebugString(sbMediaStream->Data());
OutputDebugString(L"\n");
dataWriter->WriteString(sbMediaStream);
IRandomAccessStream^ stream = mediaStream->Stream;
if (stream == nullptr)
{
throw ref new InvalidArgumentException(AttachmentValueIsNull);
}
IInputStream^ inputStream = stream->GetInputStreamAt(0);
DataReader^ dataReader = ref new DataReader(inputStream);
dataReader->UnicodeEncoding = UnicodeEncoding::Utf8;
dataReader->ByteOrder = ByteOrder::LittleEndian;
dataWriter->WriteBuffer(dataReader->ReadBuffer(dataReader->UnconsumedBufferLength));
dataWriter->WriteString(MultiPartNewLine);
facebookMediaStream->MoveNext();
} }
String^ str = ref new String(); if (mediaObject->GetValue() == nullptr)
str = MultiPartNewLine + MultiPartFormPrefix + boundary +
MultiPartFormPrefix + MultiPartNewLine;
dataWriter->WriteString(str);
}
if (mediaObjects->Size > 0)
{
IIterator<IKeyValuePair<String^, Object^>^>^ facebookMediaObject =
mediaObjects->First();
while (facebookMediaObject->HasCurrent)
{ {
String^ sbMediaObject = ref new String(); throw ref new InvalidArgumentException(AttachmentValueIsNull);
FBMediaObject^ mediaObject =
dynamic_cast<FBMediaObject^>(
facebookMediaObject->Current->Value);
if ((mediaObject->GetValue()== nullptr) ||
(mediaObject->ContentType == nullptr) ||
(mediaObject->FileName == nullptr) ||
(mediaObject->FileName->Length() == 0))
{
throw ref new InvalidArgumentException(AttachmentMustHavePropertiesSetError);
}
sbMediaObject = MultiPartFormPrefix + boundary +
MultiPartNewLine +
"Content-Disposition: form-data; name=\"" +
facebookMediaObject->Current->Key + "\"; filename=\"" +
mediaObject->FileName + "\"" + MultiPartNewLine +
"Content-Type: " + mediaObject->ContentType +
MultiPartNewLine + MultiPartNewLine;
OutputDebugString(sbMediaObject->Data());
OutputDebugString(L"\n");
dataWriter->WriteString(sbMediaObject);
if (mediaObject->GetValue() == nullptr)
{
throw ref new InvalidArgumentException(AttachmentValueIsNull);
}
dataWriter->WriteBytes(mediaObject->GetValue());
dataWriter->WriteString(MultiPartNewLine);
facebookMediaObject->MoveNext();
} }
facebookMediaObject->MoveNext();
String^ str = ref new String();
str = MultiPartNewLine + MultiPartFormPrefix + boundary +
MultiPartFormPrefix + MultiPartNewLine;
dataWriter->WriteString(str);
}
// TODO: Figure out where to get the right value for this. input
//doesn't appear to have a length at this point in the code when debugging,
contentLength = input == nullptr ? 0 : (long)input->Size;
}
else
{
// for GET,DELETE
if (mediaObjects->Size > 0 && mediaStreams->Size > 0)
{
throw ref new FailureException("Attachments (FBMediaObject/FBMediaStream) are valid only in POST requests.");
}
#if !WP8
if (httpMethod == HttpMethod::Delete)
{
queryString += L"method=delete&";
}
#endif
queryString += ParametersToQueryString(parametersWithoutMediaObjects);
}
String^ host;
String^ apiVersion = L"";
if (parametersWithoutMediaObjects->HasKey("request_host"))
{
host = static_cast<String^>(
parametersWithoutMediaObjects->Lookup("request_host"));
}
else
{
host = L"graph.facebook.com";
if (sess->APIMajorVersion)
{
apiVersion = L"v" + sess->APIMajorVersion.ToString() + L"." + sess->APIMinorVersion.ToString() + L"/";
} }
} }
// Check the path for multiple id read requests and
// modify it accordingly
const std::wstring wStringPath(path->Data());
std::size_t found = wStringPath.find(L"?ids=");
if (found != std::string::npos)
{
path += L"&";
}
else
{
path += L"?";
}
String^ uriString = L"https://" + host + L"/" + apiVersion + path + queryString;
return ref new Uri(uriString);
} }
void FBClient::SerializeParameters( void FBClient::SerializeParameters(
@ -654,8 +520,12 @@ void FBClient::SerializeParameters(
auto item = keysThatAreNotString->First(); auto item = keysThatAreNotString->First();
while (item->HasCurrent) while (item->HasCurrent)
{ {
// TODO: Jsonize the object value Object^ val = parameters->Lookup(item->Current);
String^ newValue = dynamic_cast<String^>(parameters->Lookup(item->Current)); String^ newValue = dynamic_cast<String^>(val);
if (!newValue)
{
newValue = val->ToString();
}
// Replace the existing object with the new Jsonized value // Replace the existing object with the new Jsonized value
parameters->Remove(item->Current); parameters->Remove(item->Current);
@ -667,16 +537,16 @@ void FBClient::SerializeParameters(
} }
String^ FBClient::ParametersToQueryString( String^ FBClient::ParametersToQueryString(
PropertySet^ Parameters IMapView<String^, Object^>^ parameters
) )
{ {
String^ queryString = L""; String^ queryString = L"";
// Add remaining parameters to query string. Note that parameters that // Add remaining parameters to query string. Note that parameters that
// do not need to be uploaded as multipart, i.e. any which is are not // do not need to be uploaded as multipart, i.e. any which is are not
// binary data, are required to be in the query string, even for POST // binary data, are required to be in the query string, even for POST
// requests! // requests!
IIterator<IKeyValuePair<String^, Object^>^>^ kvp = Parameters->First(); IIterator<IKeyValuePair<String^, Object^>^>^ kvp = parameters->First();
while (kvp->HasCurrent) while (kvp->HasCurrent)
{ {
String^ key = Uri::EscapeComponent(kvp->Current->Key); String^ key = Uri::EscapeComponent(kvp->Current->Key);
@ -749,3 +619,16 @@ task<String^> FBClient::TryReceiveHttpResponse(
return result; return result;
}); });
} }
PropertySet^ FBClient::MapViewToPropertySet(IMapView<String^, Object^>^ mapView)
{
PropertySet^ propertySet = ref new PropertySet();
IIterator<IKeyValuePair<String^, Object^>^>^ it = mapView->First();
while (it->HasCurrent)
{
IKeyValuePair<String^, Object^>^ current = it->Current;
propertySet->Insert(current->Key, current->Value);
it->MoveNext();
}
return propertySet;
}

Просмотреть файл

@ -42,7 +42,7 @@ namespace winsdkfb
*/ */
GetTaskAsync( GetTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
/** /**
@ -56,7 +56,7 @@ namespace winsdkfb
virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ virtual Windows::Foundation::IAsyncOperation<Platform::String^>^
PostTaskAsync( PostTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
/** /**
@ -70,7 +70,7 @@ namespace winsdkfb
virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ virtual Windows::Foundation::IAsyncOperation<Platform::String^>^
DeleteTaskAsync( DeleteTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
/** /**
@ -80,7 +80,7 @@ namespace winsdkfb
* "key1=value1&key2=value2&..." etc. * "key1=value1&key2=value2&..." etc.
*/ */
virtual Platform::String^ ParametersToQueryString( virtual Platform::String^ ParametersToQueryString(
Windows::Foundation::Collections::PropertySet^ Parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
private: private:
@ -156,7 +156,6 @@ namespace winsdkfb
* @param httpMethod Type of HTTP request to build URI for * @param httpMethod Type of HTTP request to build URI for
* @param path Request path * @param path Request path
* @param parameters Query parameters for the request * @param parameters Query parameters for the request
* @param input TODO
* @return Request URI * @return Request URI
* @exception FailureExecption if FBMediaObject or FBMediaStream are * @exception FailureExecption if FBMediaObject or FBMediaStream are
* attempting to be attached on non-POST requests. * attempting to be attached on non-POST requests.
@ -165,8 +164,7 @@ namespace winsdkfb
Windows::Foundation::Uri^ PrepareRequestUri( Windows::Foundation::Uri^ PrepareRequestUri(
winsdkfb::HttpMethod httpMethod, winsdkfb::HttpMethod httpMethod,
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters, Windows::Foundation::Collections::PropertySet^ parameters
Windows::Storage::Streams::IRandomAccessStream^ input
); );
/** /**
@ -232,5 +230,17 @@ namespace winsdkfb
concurrency::task<Windows::Web::Http::HttpResponseMessage^> httpRequestTask, concurrency::task<Windows::Web::Http::HttpResponseMessage^> httpRequestTask,
concurrency::cancellation_token_source cancellationTokenSource concurrency::cancellation_token_source cancellationTokenSource
); );
Windows::Foundation::Collections::PropertySet^ MapViewToPropertySet(
Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ mapView
);
void ValidateMediaStreams(
Windows::Foundation::Collections::PropertySet^ mediaStreams
);
void ValidateMediaObjects(
Windows::Foundation::Collections::PropertySet^ mediaObjects
);
}; };
}; };

Просмотреть файл

@ -347,7 +347,7 @@ Uri^ FacebookDialog::BuildFeedDialogUrl(
L"&redirect_uri=" + GetRedirectUriString(L"feed") + L"&redirect_uri=" + GetRedirectUriString(L"feed") +
L"&display=popup" + L"&display=popup" +
L"&app_id=" + sess->FBAppId; L"&app_id=" + sess->FBAppId;
String^ queryString = HttpManager::Instance->ParametersToQueryString(Parameters); String^ queryString = HttpManager::Instance->ParametersToQueryString(Parameters->GetView());
if (queryString->Length() > 0) if (queryString->Length() > 0)
{ {
dialogUriString += "&" + queryString; dialogUriString += "&" + queryString;
@ -372,7 +372,7 @@ Uri^ FacebookDialog::BuildRequestsDialogUrl(
L"&redirect_uri=" + GetRedirectUriString(L"requests") + L"&redirect_uri=" + GetRedirectUriString(L"requests") +
L"&display=popup" + L"&display=popup" +
L"&app_id=" + sess->FBAppId; L"&app_id=" + sess->FBAppId;
String^ queryString = HttpManager::Instance->ParametersToQueryString(Parameters); String^ queryString = HttpManager::Instance->ParametersToQueryString(Parameters->GetView());
if (queryString->Length() > 0) if (queryString->Length() > 0)
{ {
dialogUriString += "&" + queryString; dialogUriString += "&" + queryString;
@ -397,7 +397,7 @@ Uri^ FacebookDialog::BuildSendDialogUrl(
L"&redirect_uri=" + GetRedirectUriString(L"send") + L"&redirect_uri=" + GetRedirectUriString(L"send") +
L"&display=popup" + L"&display=popup" +
L"&app_id=" + sess->FBAppId; L"&app_id=" + sess->FBAppId;
String^ queryString = HttpManager::Instance->ParametersToQueryString(Parameters); String^ queryString = HttpManager::Instance->ParametersToQueryString(Parameters->GetView());
if (queryString->Length() > 0) if (queryString->Length() > 0)
{ {
dialogUriString += "&" + queryString; dialogUriString += "&" + queryString;

Просмотреть файл

@ -21,6 +21,8 @@
#include "FacebookSession.h" #include "FacebookSession.h"
#include "HttpManager.h" #include "HttpManager.h"
#include <regex>
using namespace concurrency; using namespace concurrency;
using namespace winsdkfb; using namespace winsdkfb;
using namespace winsdkfb::Graph; using namespace winsdkfb::Graph;
@ -42,6 +44,10 @@ FBPaginatedArray::FBPaginatedArray(
_parameters(Parameters), _parameters(Parameters),
_objectFactory(ObjectFactory) _objectFactory(ObjectFactory)
{ {
if (_parameters == nullptr)
{
_parameters = ref new PropertySet();
}
} }
Windows::Foundation::IAsyncOperation<FBResult^>^ FBPaginatedArray::FirstAsync( Windows::Foundation::IAsyncOperation<FBResult^>^ FBPaginatedArray::FirstAsync(
@ -228,9 +234,9 @@ Windows::Foundation::IAsyncOperation<FBResult^>^ FBPaginatedArray::GetPage(
String^ path String^ path
) )
{ {
return create_async([this, path]() -> task<FBResult^> return create_async([=]() -> task<FBResult^>
{ {
return create_task(HttpManager::Instance->GetTaskAsync(path, _parameters)) return create_task(HttpManager::Instance->GetTaskAsync(path, _parameters->GetView()))
.then([this](String^ responseString) .then([this](String^ responseString)
{ {
if (responseString == nullptr) if (responseString == nullptr)
@ -243,4 +249,4 @@ Windows::Foundation::IAsyncOperation<FBResult^>^ FBPaginatedArray::GetPage(
} }
}); });
}); });
} }

Просмотреть файл

@ -99,7 +99,7 @@ FBSession::FBSession() :
login_evt = CreateEventEx(NULL, NULL, 0, DELETE | SYNCHRONIZE); login_evt = CreateEventEx(NULL, NULL, 0, DELETE | SYNCHRONIZE);
} }
_APIMajorVersion = 2; _APIMajorVersion = 2;
_APIMinorVersion = 1; _APIMinorVersion = 6;
#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP #if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
_webViewRedirectDomain = FACEBOOK_MOBILE_SERVER_NAME; _webViewRedirectDomain = FACEBOOK_MOBILE_SERVER_NAME;
#else #else
@ -160,6 +160,9 @@ FBAccessTokenData^ FBSession::AccessTokenData::get()
void FBSession::AccessTokenData::set(FBAccessTokenData^ value) void FBSession::AccessTokenData::set(FBAccessTokenData^ value)
{ {
_AccessTokenData = value; _AccessTokenData = value;
// If token have been updated, make sure to save updated token
TrySaveTokenData();
} }
FBUser^ FBSession::User::get() FBUser^ FBSession::User::get()
@ -205,9 +208,12 @@ task<FBResult^> FBSession::GetUserInfo(
winsdkfb::FBAccessTokenData^ TokenData winsdkfb::FBAccessTokenData^ TokenData
) )
{ {
PropertySet^ parameters = ref new PropertySet();
parameters->Insert(L"fields",
L"gender,link,first_name,last_name,locale,timezone,email,updated_time,verified,name,id");
FBSingleValue^ value = ref new FBSingleValue( FBSingleValue^ value = ref new FBSingleValue(
"/me", "/me",
nullptr, parameters,
ref new FBJsonClassFactory([](String^ JsonText) -> Object^ ref new FBJsonClassFactory([](String^ JsonText) -> Object^
{ {
return FBUser::FromJson(JsonText); return FBUser::FromJson(JsonText);
@ -961,7 +967,6 @@ IAsyncOperation<FBResult^>^ FBSession::LoginAsync(
{ {
Permissions = ref new FBPermissions((ref new Vector<String^>())->GetView()); Permissions = ref new FBPermissions((ref new Vector<String^>())->GetView());
} }
_dialog = ref new FacebookDialog();
return create_async([=]() return create_async([=]()
{ {

Просмотреть файл

@ -0,0 +1,145 @@
//******************************************************************************
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//******************************************************************************
#include "pch.h"
#include "GraphUriBuilder.h"
#include "FacebookSession.h"
#include <regex>
#include <sstream>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace winsdkfb;
GraphUriBuilder::GraphUriBuilder(String^ path)
:
_queryParams { ref new PropertySet() }
{
Uri^ testUri;
bool buildDomain = false;
try
{
testUri = ref new Uri(path);
}
catch (Platform::InvalidArgumentException^ e)
{
buildDomain = true;
}
if (buildDomain)
{
String^ domain = L"https://graph.facebook.com/";
testUri = ref new Uri(domain + path);
}
_host = testUri->Host;
_path = testUri->Path;
_scheme = testUri->SchemeName;
// remove any extra '/'s from path
FixPathDelimiters();
// capture api version from path or build it
BuildApiVersionString();
// save query params in map for later use
DecodeQueryParams(testUri);
}
void GraphUriBuilder::AddQueryParam(Platform::String^ query, Platform::String^ param)
{
_queryParams->Insert(query, param);
}
Windows::Foundation::Uri^ GraphUriBuilder::MakeUri()
{
// this request_host stuff is a bit of a hack to send graph calls in
// the unit tests to our own web service.
if (_queryParams->HasKey(L"request_host"))
{
_host = static_cast<String^>(_queryParams->Lookup(L"request_host"));
}
String^ fullPath = _scheme + L"://" + _host + L"/" + _apiVersion + _path;
if (_queryParams->Size > 0)
{
String^ separator = L"?";
auto it = _queryParams->First();
while (it->HasCurrent)
{
fullPath += separator + Uri::EscapeComponent(it->Current->Key) + L"=" + Uri::EscapeComponent(static_cast<String^>(it->Current->Value));
separator = L"&";
it->MoveNext();
}
}
return ref new Uri(fullPath);
}
void GraphUriBuilder::BuildApiVersionString()
{
std::wstring regexString = LR"__(^.?(v\d\.\d)(.*))__";
std::wregex apiRegex{ regexString };
std::wsmatch match;
std::wstring searchString{ _path->Data() };
std::regex_match(searchString, match, apiRegex);
if (match.size() >= 3) // 1 for matched string + 2 for each capture group
{
std::wstring apiString = match[1].str();
_apiVersion = ref new String(apiString.c_str());
// need to adjust _path so that the api version doesn't get added twice
std::wstring newPath = match[2].str();
_path = ref new String(newPath.c_str());
}
else
{
FBSession^ sess = FBSession::ActiveSession;
if (sess->APIMajorVersion)
{
_apiVersion = "v" + sess->APIMajorVersion.ToString() + "." + sess->APIMinorVersion.ToString();
}
}
}
void GraphUriBuilder::FixPathDelimiters()
{
String^ fixedPath = L"";
std::wstring originalPath{ _path->Data() };
std::wistringstream iss{ originalPath };
std::wstring token;
while (std::getline(iss, token, L'/'))
{
if (token.size() > 0)
{
fixedPath += L"/" + ref new String(token.c_str());
}
}
_path = fixedPath;
}
void GraphUriBuilder::DecodeQueryParams(Uri^ uri)
{
WwwFormUrlDecoder^ decoder = uri->QueryParsed;
if (decoder->Size > 0)
{
IIterator<IWwwFormUrlDecoderEntry^>^ it = decoder->First();
while (it->HasCurrent)
{
IWwwFormUrlDecoderEntry^ current = it->Current;
_queryParams->Insert(current->Name, current->Value);
it->MoveNext();
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
//******************************************************************************
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//******************************************************************************
#pragma once
#include <ppltasks.h>
namespace winsdkfb
{
public ref class GraphUriBuilder sealed
{
public:
GraphUriBuilder(Platform::String^ path);
Windows::Foundation::Uri^ MakeUri();
void AddQueryParam(Platform::String^ query, Platform::String^ param);
private:
void BuildApiVersionString();
void FixPathDelimiters();
void DecodeQueryParams(Windows::Foundation::Uri^ uri);
Platform::String^ _host;
Platform::String^ _path;
Platform::String^ _scheme;
Platform::String^ _apiVersion;
Windows::Foundation::Collections::PropertySet^ _queryParams;
};
}

Просмотреть файл

@ -34,23 +34,23 @@ void HttpManager::SetHttpClient(IHttpClient^ httpClient)
_httpClient = httpClient; _httpClient = httpClient;
} }
IAsyncOperation<String^>^ HttpManager::GetTaskAsync(String^ path, PropertySet^ parameters) IAsyncOperation<String^>^ HttpManager::GetTaskAsync(String^ path, IMapView<String^, Object^>^ parameters)
{ {
return _httpClient->GetTaskAsync(path, parameters); return _httpClient->GetTaskAsync(path, parameters);
} }
IAsyncOperation<String^>^ HttpManager::PostTaskAsync(String^ path, PropertySet^ parameters) IAsyncOperation<String^>^ HttpManager::PostTaskAsync(String^ path, IMapView<String^, Object^>^ parameters)
{ {
return _httpClient->PostTaskAsync(path, parameters); return _httpClient->PostTaskAsync(path, parameters);
} }
IAsyncOperation<String^>^ HttpManager::DeleteTaskAsync(String^ path, PropertySet^ parameters) IAsyncOperation<String^>^ HttpManager::DeleteTaskAsync(String^ path, IMapView<String^, Object^>^ parameters)
{ {
return _httpClient->DeleteTaskAsync(path, parameters); return _httpClient->DeleteTaskAsync(path, parameters);
} }
String^ HttpManager::ParametersToQueryString( String^ HttpManager::ParametersToQueryString(
PropertySet^ Parameters IMapView<String^, Object^>^ Parameters
) )
{ {
return _httpClient->ParametersToQueryString(Parameters); return _httpClient->ParametersToQueryString(Parameters);

Просмотреть файл

@ -34,21 +34,21 @@ namespace winsdkfb
virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ GetTaskAsync( virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ GetTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ PostTaskAsync( virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ PostTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ DeleteTaskAsync( virtual Windows::Foundation::IAsyncOperation<Platform::String^>^ DeleteTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
virtual Platform::String^ ParametersToQueryString( virtual Platform::String^ ParametersToQueryString(
Windows::Foundation::Collections::PropertySet^ Parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
private: private:

Просмотреть файл

@ -23,21 +23,21 @@ namespace winsdkfb
public: public:
Windows::Foundation::IAsyncOperation<Platform::String^>^ GetTaskAsync( Windows::Foundation::IAsyncOperation<Platform::String^>^ GetTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
Windows::Foundation::IAsyncOperation<Platform::String^>^ PostTaskAsync( Windows::Foundation::IAsyncOperation<Platform::String^>^ PostTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
Windows::Foundation::IAsyncOperation<Platform::String^>^ DeleteTaskAsync( Windows::Foundation::IAsyncOperation<Platform::String^>^ DeleteTaskAsync(
Platform::String^ path, Platform::String^ path,
Windows::Foundation::Collections::PropertySet^ parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
Platform::String^ ParametersToQueryString( Platform::String^ ParametersToQueryString(
Windows::Foundation::Collections::PropertySet^ Parameters Windows::Foundation::Collections::IMapView<Platform::String^, Platform::Object^>^ parameters
); );
}; };
} }

Просмотреть файл

@ -56,6 +56,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)pch.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)pch.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ScaleConverter.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)ScaleConverter.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)SDKMessage.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)SDKMessage.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)GraphUriBuilder.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)ColorLuminosityConverter.cpp" /> <ClCompile Include="$(MSBuildThisFileDirectory)ColorLuminosityConverter.cpp" />
@ -96,6 +97,7 @@
<PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)ScaleConverter.cpp" /> <ClCompile Include="$(MSBuildThisFileDirectory)ScaleConverter.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)GraphUriBuilder.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectCapability Include="SourceItemsFromImports" /> <ProjectCapability Include="SourceItemsFromImports" />

Просмотреть файл

@ -85,6 +85,9 @@
<ClCompile Include="$(MSBuildThisFileDirectory)HttpManager.cpp"> <ClCompile Include="$(MSBuildThisFileDirectory)HttpManager.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)GraphUriBuilder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)FacebookDialog.xaml.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)FacebookDialog.xaml.h" />
@ -189,6 +192,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)FBConstants.h"> <ClInclude Include="$(MSBuildThisFileDirectory)FBConstants.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)GraphUriBuilder.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="$(MSBuildThisFileDirectory)Images\fb_blank_profile_portrait.png" /> <Image Include="$(MSBuildThisFileDirectory)Images\fb_blank_profile_portrait.png" />

Просмотреть файл

@ -98,6 +98,10 @@
<None Include="..\..\FBWinStoreCsTests\FBCSObjectImplementation.ttinclude"> <None Include="..\..\FBWinStoreCsTests\FBCSObjectImplementation.ttinclude">
<Link>FBCSObjectImplementation.ttinclude</Link> <Link>FBCSObjectImplementation.ttinclude</Link>
</None> </None>
<Content Include="..\..\FBWinStoreCsTests\TestData\testJsonPropertySet.json">
<Link>TestData\testJsonPropertySet.json</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="..\..\FBWinStoreCsTests\Utility.ttinclude"> <None Include="..\..\FBWinStoreCsTests\Utility.ttinclude">
<Link>Utility.ttinclude</Link> <Link>Utility.ttinclude</Link>
</None> </None>

Просмотреть файл

@ -170,7 +170,7 @@ IAsyncOperation<String^>^ FBSDKAppEvents::LogInstallEvent(
parameters->Insert(L"windows_attribution_id", campaignID); parameters->Insert(L"windows_attribution_id", campaignID);
return create_task([=]() -> IAsyncOperation<String^>^ return create_task([=]() -> IAsyncOperation<String^>^
{ {
return HttpManager::Instance->PostTaskAsync(path, parameters); return HttpManager::Instance->PostTaskAsync(path, parameters->GetView());
}); });
} }
catch (Platform::Exception^ ex) catch (Platform::Exception^ ex)
@ -206,7 +206,7 @@ IAsyncAction^ FBSDKAppEvents::LogActivateEvent(
return create_async([=]() return create_async([=]()
{ {
return create_task(HttpManager::Instance->PostTaskAsync(path, parameters)) return create_task(HttpManager::Instance->PostTaskAsync(path, parameters->GetView()))
.then([=](String^ response) -> void .then([=](String^ response) -> void
{ {
#ifdef _DEBUG #ifdef _DEBUG