Looking for VS2010 support

Aug 4, 2014 at 9:51 AM
HI,Our IT department demand us to use an authorised edition of VS2010, I'm now developing an HTTP client on Win7 using C++ REST and want the program run on XP or Win7. But there seems little support for VS2010 and no documents, user guidance, API statements to help install and use the SDK. Where can I get these informations?
Coordinator
Aug 4, 2014 at 4:45 PM
Hi joeccmou,

Our latest release don't support Visual Studio 2010 any more, only 2012 and 2013 currently. Mainly due to compiler and standard library features that are present in newer versions. If you can't use a newer version then you could stick with one of our older releases. The last one that we produced binaries for 2010 was 1.2.0. If you want to build from source the last version that contained the 2010 project files was 1.3.1.

Regardless of the release you're using I recommend you use our NuGet packages. Here is a tutorial using the http_client consuming our NuGet package. If you aren't using our latest release you will need to use the NuGet package manager console to specify the version, i.e. "Install-Package cpprestsdk -Version 1.2.0"

Here is a prior discussion, about the end of Visual Studio 2010 support.

Steve
Aug 5, 2014 at 11:32 AM
Edited Aug 5, 2014 at 11:39 AM
1
Aug 5, 2014 at 11:38 AM
stevetgates wrote:
Hi joeccmou,

Our latest release don't support Visual Studio 2010 any more, only 2012 and 2013 currently. Mainly due to compiler and standard library features that are present in newer versions. If you can't use a newer version then you could stick with one of our older releases. The last one that we produced binaries for 2010 was 1.2.0. If you want to build from source the last version that contained the 2010 project files was 1.3.1.

Regardless of the release you're using I recommend you use our NuGet packages. Here is a tutorial using the http_client consuming our NuGet package. If you aren't using our latest release you will need to use the NuGet package manager console to specify the version, i.e. "Install-Package cpprestsdk -Version 1.2.0"

Here is a prior discussion, about the end of Visual Studio 2010 support.

Steve
Thank you for your attention. I have read the prior discussion, it seems that version 1.2.0 doesn't run stably on XP. If I want to run my program on both XP and Win7, does it mean I need to write my codes on VS2013 with the last version of C++ REST SDK?
Coordinator
Aug 5, 2014 at 6:28 PM
Hi,

Yes the 1.2 release was the first one containing XP support, but it probably will still work fine. The other option is to build for Windows from source with the 1.3.0 release.

In general I'd strongly advise you to use Visual Studio 2012 or 2013 so you can take advantage of our later releases. Each release contains more features and numerous bug fixes and improvements. What about using Visual Studio 2013 Desktop Express?

Steve
Aug 7, 2014 at 3:03 AM
Edited Aug 7, 2014 at 12:24 PM
HI Steve,
    Thank you for your replay. I'm now use VS2013 and the latest version C++ REST SDK 2.1, but I encounter a problem that which binary file should I choose between bin\win32\v120 and bin\win32\v120_xp if I want my program run on both XP and WIN7 ?
Coordinator
Aug 7, 2014 at 5:29 PM
Hi joeccmou,

If you want to support running on XP then you have to choose to use the 'xp' version of our binaries. This is because some APIs are not available until Vista, so some of parts of our implementation are different.

If you are directly using the NuGet package you can do this by selecting the Platform Toolset to be Visual Studio 2013 - Windows XP (v120_xp).

Steve
Aug 8, 2014 at 5:18 AM
Edited Aug 11, 2014 at 3:27 AM
Hi Steve
     Thank you for your advise, I have moved the BingRequest  into my project and build successfully. But now I  encounter a problem that the program seems to be trapped in the "client.request" function. 
     I follow the debug info and find that when it runs into the http_request constructor, it never returns.
    pplx::task<http_response> request(
    method mtd, 
    const utility::string_t &path_query_fragment,
    pplx::cancellation_token token = pplx::cancellation_token::none())
{
    http_request msg(std::move(mtd));              //the program runs to here
    msg.set_request_uri(path_query_fragment);   // and never come here
    return request(msg, token);
}
       The BingRequest demo can run the above code normally. I merely put the code from BingRequest into void CFingerPrintView::OnAccessServer() like following, where  OnAccessServer() is a function which responses to a click on the pull-down menu.
 const string_t searchTerm(U("bing"));
 const string_t outputFileName(U("bing.html"));

// Open a stream to the file to write the HTTP response body into.
auto fileBuffer = std::make_shared<streambuf<uint8_t>>();
file_buffer<uint8_t>::open(outputFileName, std::ios::out).then([=](streambuf<uint8_t> outFile) -> pplx::task<http_response>
{
    *fileBuffer = outFile; 

        // Create an HTTP request.
    // Encode the URI query since it could contain special characters like spaces.
    http_client client(U("http://www.bing.com/"));
    return client.request(methods::GET, uri_builder(U("/search")).append_query(U("q"), searchTerm).to_string());
})

    // Write the response body into the file buffer.
    .then([=](http_response response) -> pplx::task<size_t>
{
    printf("Response status code %u returned.\n", response.status_code());

    return response.body().read_to_end(*fileBuffer);
})

    // Close the file buffer.
    .then([=](size_t)
{
    return fileBuffer->close();
})

// Wait for the entire response body to be written into the file.
.wait();
    The debug prompt is 
Debug Assertion Failed!

Program: ...ign\VC++\FingerPrint\FingerPrint Client\Debug\Fingerprint.exe
File: f:\dd\vctools\crt\crtw32\misc\dbgheap.c
Line: 1424

Expression: _pFirstBlock == pHead

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
and the called stack is ( reversely )
  1. msvcr120d.dll!_free_dbg_nolock(void * pUserData, int nBlockUse) 行 1424 C++
  2. msvcr120d.dll!_free_dbg(void * pUserData, int nBlockUse) 行 1265 C++
  3. msvcr120d.dll!operator delete(void * pUserData) 行 54 C++
  4. cpprest120d_xp_2_1.dll!std::allocator<struct std::_Container_proxy>::deallocate(struct std::_Container_proxy *,unsigned int) 未知
  5. cpprest120d_xp_2_1.dll!std::_String_alloc<0,struct std::_String_base_types<wchar_t,class std::allocator<wchar_t> > >::_Free_proxy(void) 未知
  6. cpprest120d_xp_2_1.dll!std::_String_alloc<0,struct std::_String_base_types<wchar_t,class std::allocator<wchar_t> > >::~_String_alloc<0,struct std::_String_base_types<wchar_t,class std::allocator<wchar_t> > >(void) 未知
  7. cpprest120d_xp_2_1.dll!std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >::~basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >(void) 未知
  8. cpprest120d_xp_2_1.dll!web::http::details::_http_request::_http_request(class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >) 未知
  9. Fingerprint.exe!std::_Ref_count_obj<web::http::details::_http_request>::_Ref_count_obj<web::http::details::_http_request><std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > && <_Args_0>) 行 932 C++
  10. Fingerprint.exe!std::make_shared<web::http::details::_http_request,std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > && <_Args_0>) 行 1003 C++
  11. Fingerprint.exe!web::http::http_request::http_request(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > mtd) 行 736 C++
  12. Fingerprint.exe!web::http::client::http_client::request(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > mtd, const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & path_query_fragment, Concurrency::cancellation_token token) 行 351 C++
  13. Fingerprint.exe!CFingerPrintView::OnAccessServer::__l3::<lambda>(Concurrency::streams::streambuf<unsigned char> outFile) 行 2187 C++
    CFingerPrintApp is a single document MFC application with platform toolset  "visual studio 2013 - Window XP (v120_xp)",  character set "Unicode" and " use MFC  with static linking". 
Coordinator
Aug 11, 2014 at 9:43 PM
Hi joeccmou,

The problem is with static linking, you are ending up with 2 heaps in the same process and this can cause all sorts of problems. STL data structures are being allocated on one and attempted to be freed on the other. I took your exact code here and ran no problem in an MFC application if I used "Use of MFC" as "Use MFC in a Shared DLL". My recommendation is to avoid static linking if you can.

We currently don't officially support static linking yet, but have a feature request open for it that you could vote on. Alternately some people have been successful building and using static linking themselves. The feature request contains a link to a blog explaining how someone has accomplished it.

Steve
Aug 12, 2014 at 6:30 AM
Edited Aug 12, 2014 at 7:29 AM
Hi Steve

I have read the feature request, and try the method written in the blog and methods written by c273 in the issue's discussions.
I think the main opinion is to rebuild the casablanca120.xp and generate a static lib. But when I rebuild casablanca120.xp project and use cpprest120d_xp_2_1.lib in my project, I encounter a link problem like the following
cpprest120d_xp_2_1.lib(http_msg.obj) : error LNK2005: "public: __thiscall web::http::details::_http_request::_http_request(class std::basic_string<wchar_t,struct sd::char_traits<wchar_t>,class std::allocator<wchar_t> >)" (??0_http_request@details@http@web@@QAE@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z) has been defined in cpprest120d_xp_2_1.lib(cpprest120d_xp_2_1.dll)
It seems cpprest120d_xp_2_1.lib contains cpprest120d_xp_2_1.dll. How to solve this problem?

PS:
I have made a mistake that I import the static cpprest120d_xp_2_1.lib without removing the C++ REST SDK from my project. After removing the C++ REST SDK by NuGet,  the static linked program runs successfully. Just leave the above link error as a prompt  for the future C++ REST users.

Thank you very much and all the appreciating work done by this community.
joeccmou
Aug 12, 2014 at 1:03 PM
Edited Aug 12, 2014 at 2:16 PM
Hi steve,

I try to use JSON value like the JSON Demo) . But I can't retrieve a JSON value from the http response object while the http response body can convert to the right return string from my server. The response header is as following:

Cache-Control: private
Content-Length: 225
Content-Type : application/json; charset=utf-8
Server: Microsoft-IIS/6.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET


The response reason phrase is "OK". And my application is a MFC single doc win32 application with lib option "Use of MFC" and static cpprest120d_xp_2_1.lib as discussed above. The response body can convert to the right string as following

[{"Company":null,"CompanyName":"goodix","Name":"000001"},{"Company":null,"CompanyName":"goodix","Name":"000002"},{"Company":null,"CompanyName":"goodix","Name":"000003"},{"Company":null,"CompanyName":"goodix","Name":"000004"}]

The source code is
    container_buffer<std::string> inStringBuffer;
    http_response http_resp;
    client.request(request).then([&http_resp](http_response sp)
{
    http_resp = sp; //Well, I don't know how to get a task return value after it completes without Lambda expression
})
.wait();

json::value obj;
istream bodyStream;

if (http_resp.status_code() == status_codes::OK)
{

        bodyStream = http_resp.body();    
        bodyStream.read_to_end(inStringBuffer);    

        pplx::task<json::value> json_task;
        http_resp.extract_json().then([&json_task](pplx::task<json::value> js)
        {
            json_task = js;
        })
        .wait();
        if (json_task.is_done())                
        {
            try
            {
                const json::value& v = json_task.get();   //just get the json value, but it raise an exception
                obj = v;

            }
            catch (const http_exception& e)
            {                       
                const char *excep_info = e.what();                 // though raise an exception, the program never come here, how can i know exactly what it is
                std::cout << excep_info << std::endl;
            }
        }
        size_t json_size = obj.size();          
      }

the call stack is
KernelBase.dll!_RaiseException@16()    undefined
Fingerprint.exe!__ExceptionPtr::_RethrowException() line 626    C++
Fingerprint.exe!__ExceptionPtrRethrow(const void * _ptr) line 690   C++
Fingerprint.exe!std::exception_ptr::_RethrowException() line 467    C++
Fingerprint.exe!std::rethrow_exception(std::exception_ptr _P) line 535  C++
Fingerprint.exe!Concurrency::details::_ExceptionHolder::_RethrowUserException() line 931    C++
Fingerprint.exe!Concurrency::details::_Task_impl_base::_Wait() line 1779    C++
Fingerprint.exe!Concurrency::task<web::json::value>::get() line 3490    C++
Fingerprint.exe!CFingerPrintView::OnAccessServer() line 2359    C++
And I try the demo code by little modified and succeed. Still have a few questions
    if (http_resp.status_code() == status_codes::OK)
{

        //bodyStream = http_resp.body();   //if I read the body to a buffer, then get json value fail
        //bodyStream.read_to_end(inStringBuffer);    

        pplx::task<json::value> json_task;
        http_resp.extract_json().then([&obj](pplx::task<json::value> previousTask)
        {
        //  json_task = previousTask;   // cannot copy a task?
            try
            {                   
                const json::value& v = previousTask.get();
                //obj = v.;                // cannot copy a json::value object?             
            }
            catch (const http_exception& e)
            {
                // Print error.         
                const char *excep_info = e.what();
                std::cout << excep_info << std::endl;
            }
        });
        }
joeccmou
Coordinator
Aug 12, 2014 at 3:58 PM
Hi joeccmou,

Yes the reason your first bit of code is failing is because you first directly read all the data from the http_response body into a stream. This is destructive, once you've read the data it no longer is in the stream. So when you go to call extract_json there is no data left to read. You can only consume the response body once so you have to choose which method you want.

In your second example your json_task = previousTask assignment is probably failing because you don't have the json_task variable captured in your lambda, so the compiler doesn't know about it. Please note if you wanted the save the task from the extract_json() function call you could just do something like:
pplx::task<json::value> json_task = http_resp.extract_json();
json_task.then([&obj](pplx::task<json::value> previousTask)
...
Also json::value supports copying, what is the error you are getting?

Unrelated note - this thread is getting long, for new items to discuss I recommend to start a new discussion.

Thanks,
Steve
Aug 14, 2014 at 9:15 AM
Hi Steve,
         Thank you for reply.  I have been much more familiar with C++ REST.
Joecc