Put method in asp.net mvc REST service - asp.net-mvc

I put data to my api using the code below:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PutAsJsonAsync($"/api/Home/UpdateEmpDetails/{id}", newEmployee).Result;
if (response.IsSuccessStatusCode)
{
//...
}
}
but I get the following error:
{StatusCode: 405, ReasonPhrase: 'Method Not Allowed', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { X-Powered-By-Plesk: PleskWin Connection: close Date: Thu, 05 Oct 2017 05:26:07 GMT Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET Content-Length: 1293 Allow: GET Allow: HEAD Allow: OPTIONS Allow: TRACE Content-Type: text/html }}
can anyone help me?

WebDAV module may cause 405 error, so make sure you have WebDAV module not installed. Check if it is installed from Control Panel > "Turn Windows Features On or Off". If you don’t need to use WebDAV then remove "WebDAV Publishing" to fix "405 method not allowed" issue.
Or you may it fix it for only this project by adding the following to web.config of your WebApi project:
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/> <!-- add to remove webdav -->
</modules>

Related

gzip compression doesn't work and can't get 304 in chrome

I'm working on a compression and caching mechanism in my asp.net mvc 5 app.
I'm sending files with the following cache headers:
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetExpires(DateTime.UtcNow.AddYears(1).ToUniversalTime());
Response.Cache.SetLastModified(System.IO.File.GetLastWriteTime(serverPath).ToUniversalTime());
Response.AppendHeader("Vary", "Accept-Encoding");
IE11, Edge, Firefox, all sends the If-Modified-Since header on F5 refresh, but not Chrome. Why is that and how to workaround it? In Chrome I got 200 status code and file is loaded from cache.
The second problem I have is with enabling gzip compression.
I have a standard action filter for this:
public class CompressContentMvcAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
GZipEncodePage();
}
private bool IsGZipSupported()
{
string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];
if (!string.IsNullOrEmpty(AcceptEncoding) &&
(AcceptEncoding.Contains("gzip") || AcceptEncoding.Contains("deflate")))
{
return true;
}
return false;
}
private void GZipEncodePage()
{
HttpResponse Response = HttpContext.Current.Response;
if (IsGZipSupported())
{
string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];
if (AcceptEncoding.Contains("gzip"))
{
Response.Filter = //new GZipCompressionService().CreateCompressionStream(Response.Filter);
new System.IO.Compression.GZipStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.Headers.Remove("Content-Encoding");
Response.AppendHeader("Content-Encoding", "gzip");
}
else
{
Response.Filter =// new DeflateCompressionService().CreateCompressionStream(Response.Filter);
new System.IO.Compression.DeflateStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.Headers.Remove("Content-Encoding");
Response.AppendHeader("Content-Encoding", "deflate");
}
}
// Allow proxy servers to cache encoded and unencoded versions separately
Response.AppendHeader("Vary", "Content-Encoding");
}
}
I apply this filter on my action method returning application assets, but it got the Transfer-Encoding: chunked for each file, not gziped.
This filter is copied from my previous project and there it is still working at is expected. Could it be a problem with IIS server? Locally I have a IIS 10 and .NET 4.7, the the older app, where it works is hosted on IIS 8.5 and framework 4.5. Can't think of anything else. I'm googling the second day and can't find any clue.
I'm not interested in compressing in IIS.
[edit]
Header I got from response:
HTTP/1.1 200 OK
Cache-Control: public
Content-Type: text/javascript
Expires: Sat, 18 May 2019 08:58:48 GMT
Last-Modified: Thu, 10 May 2018 13:26:02 GMT
Vary: Content-Encoding
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 18 May 2018 08:58:48 GMT
Transfer-Encoding: chunked
I always use Fiddler to inspect these kind of challenges.
The F5/If-Modified-Since issue.
Chrome just doesn't make a new request if the expires header has been set and its datetime value is still actual. So Chrome is respecting your expected caching behaviour. When navigating over your website via an other browser, you 'll see that also these don't send any requests for these assets. F5 is 'special', it's a forced refresh.
The chunked/gzip issue
Clear your browser cache and inspect the first response. Fiddler will show 'Response body is encoded', which means compressed (gzip or deflate).
Whether you see Transfer-Encoding chunked depends on whether the Content-Length header is present. See the difference in the responses below. If you don't want the chunked Transfer-Encoding set the Content-Length header.
Content-Type: text/javascript; charset=utf-8
Content-Encoding: gzip
Expires: Sat, 25 May 2019 13:14:11 GMT
Last-Modified: Fri, 25 May 2018 13:14:11 GMT
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
Content-Length: 5292
Content-Type: text/javascript; charset=utf-8
Transfer-Encoding: chunked
Content-Encoding: gzip
Expires: Sat, 25 May 2019 13:14:11 GMT
Last-Modified: Fri, 25 May 2018 13:14:11 GMT
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
Because you are handling the serving of assets via your own code, instead of via the IIS static files module, you have to deal with all response headers yourself.

How implement a OData V4 services like official example services?

The example services mean this:
http://services.odata.org/V4/Northwind/Northwind.svc/
My question is:
Why this service has a ".svc" suffix? As I know, now only two ways can implement odata v4 services on .Net platform, RESTier and WebAPI, see http://odata.github.io/, but both of them not have ".svc". In fact, wcf data services has ".svc", but wcfds not support odata v4.
This example service's response body is high optimization, like this:
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 2015
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Expires: Sat, 24 Oct 2015 05:10:34 GMT
Vary: *
Server: Microsoft-IIS/8.0
X-Content-Type-Options: nosniff
OData-Version: 4.0;
X-AspNet-Version: 4.0.30319
...
{"#odata.context":"http://services.odata.org/V4/Northwind/Northwind.svc/$metadata","value":[{"name":"Categories","kind":"EntitySet","url":"......
just one line, like wcfds again, but my service like this:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; odata.metadata=minimal; charset=utf-8
Expires: -1
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
OData-Version: 4.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 24 Oct 2015 06:56:24 GMT
Content-Length: 364
{
"#odata.context":"http://192.168.1.99:908/api/$metadata","value":[
{
"name":"Test","kind":"EntitySet","url":"Test"
},{
"name":"TDefStoreEmp","kind":"EntitySet","url":"TDefStoreEmp"
},{
"name":"TDefEmp","kind":"EntitySet","url":"TDefEmp"
},{
"name":"TDefStore","kind":"EntitySet","url":"TDefStore"
}
]
}
too many lines, how did one line?
So I suspect the example service is based on wcfds, but how it can support V4? in fact, i like wcfds, because it don't need any Controllers, i just want expose a database but don't want open 1433 port on the internet.
My english is not good, please understand and help me, thanks!
You are right, this demo service is implemented using WCF Data Service.
For web api based demo service, you can refer to :
http://services.odata.org/TripPinWebApiService
WCF Data Service for OData V4 is not officially supported, and it is recommended to use WebAPI instead.
This is called indent for JSON, and it was enabled by default.
To disable indent, please add the following to your webapi configuration code:
var formatters = ODataMediaTypeFormatters.Create();
foreach (var formatter in formatters)
{
formatter.MessageWriterSettings.Indent = false;
}
config.Formatters.InsertRange(0, formatters);
The source WCF Data Service is public visible here:
https://github.com/OData/odata.net/tree/WCFDSV4
Please note that the implementation indeed has some gap with OData V4 spec. But if you are interested, you can feel free to build it by yourself it or add new features.
As suggested, it's recommended to use WebAPI OData for setting up OData V4 service. Also, you could choose to use RESTier which resembles wcfds style more.
If you are looking for TripPin OData sample you can find it here:
https://github.com/OData/ODataSamples/tree/master/Scenarios/TripPin

Update payment in open-source QuickBooks PHP DevKit on GitHub

I am using the open-source QuickBooks PHP DevKit on GitHub. I am trying to update a payment. But I am getting an error "ERROR!2030: [Invalid ID, Id should be a valid number. Supplied value:{-17}]"
Code I had given is shown below
First added code for update function in Quickbooks/IPP/Service/Payment.php like below:
public function update($Context, $realm, $IDType, $Object)
{
return parent::_update($Context, $realm, QuickBooks_IPP_IDS::RESOURCE_PAYMENT, $Object, $IDType);
}
After that in the payment_update.php page, I added the code as given below:
$IPP->version(QuickBooks_IPP_IDS::VERSION_3);
$PaymentService = new QuickBooks_IPP_Service_Payment();
$payments = $PaymentService->query($Context, $realm, "SELECT * FROM Payment where Id='27'");
$Payment = $payments[0];
$Payment->setPaymentRefNum("5Update");
if ($resp = $PaymentService->update($Context, $realm, $Payment->getId(), $Payment))
{
print('Updated the item name to ' . $Payment->getTotalAmt());
}
else
{
print('ERROR!');
print($PaymentService->lastError($Context));
}
Do I need to add any other changes in the class file for updating a payment. Please advise how can I update payment & line.
Request:
POST https://quickbooks.api.intuit.com/v3/company/1214054285/payment HTTP/1.1
Content-Type: application/xml
Authorization: OAuth realm="", oauth_signature_method="HMAC-SHA1", oauth_signature="XXXX", oauth_nonce="zVYx5", oauth_timestamp="1402573818", oauth_token="XXXX", oauth_consumer_key="XXXXX", oauth_version="1.0"
Content-Length: 1023
<Payment xmlns="http://schema.intuit.com/finance/v3">
<Id>27</Id>
<SyncToken>1</SyncToken>
<MetaData xmlns="http://schema.intuit.com/finance/v3">
<CreateTime>2014-06-12T00:36:12-07:00</CreateTime>
<LastUpdatedTime>2014-06-12T00:37:44-07:00</LastUpdatedTime>
</MetaData>
<Line xmlns="http://schema.intuit.com/finance/v3">
<Amount>12.00</Amount>
<LinkedTxn xmlns="http://schema.intuit.com/finance/v3">
<TxnId>{-17}</TxnId>
<TxnType>Invoice</TxnType>
</LinkedTxn>
</Line>
<Line xmlns="http://schema.intuit.com/finance/v3">
<Amount>5.00</Amount>
<LinkedTxn xmlns="http://schema.intuit.com/finance/v3">
<TxnId>{-13}</TxnId>
<TxnType>Invoice</TxnType>
</LinkedTxn>
</Line>
<TxnDate>2014-05-11</TxnDate>
<CurrencyRef>USD</CurrencyRef>
<CustomerRef>12</CustomerRef>
<DepositToAccountRef>18</DepositToAccountRef>
<PaymentRefNum>5Update</PaymentRefNum>
<TotalAmt>17.00</TotalAmt>
<UnappliedAmt>0</UnappliedAmt>
<ProcessPayment>false</ProcessPayment>
</Payment>
Response:
HTTP/1.1 400 Bad Request
Date: Thu, 12 Jun 2014 11:49:09 GMT
Content-Type: application/xml
Content-Length: 285
intuit_tid: ae570ca6-4f46-4132-978d-f12f394c50d2
Content-Encoding: gzip
Via: 1.1 ipp-gateway-.net
Vary: Accept-Encoding
Connection: close
This was fixed in an update several months ago.
Please use the latest code from GitHub and you should be all set:
https://github.com/consolibyte/quickbooks-php

ASP.NET Web API and MonoDroid

I am trying to call a ASP.NET Web API that I have hosted in IIS from MonoDroid. The service is fine and I can call it from different endpoints. The problem is that in MonoDroid I get invalid cast exception when I try to do this.
var s = response.GetResponseStream();
var j = (JsonObject)JsonObject.Load(s);
System.InvalidCastException: comes back on the load part.
I have done some reading and people seem to say to try to switch the Web API to use JsonNetFormatter class. I tried that and still no luck.
Anybody have any ideas on what I can try?
UPDATE
Here is payload
<ArrayOfAlbum xmlns:xsi="w3.org/2001/XMLSchema-instance";
xmlns:xsd="w3.org/2001/XMLSchema">;
<Album>
<AlbumPK>f09d14cf-3bab-44c8-b614-2b7cf728efd4</AlbumPK>
<Name>Colorado</Name>
<UserName>firstUser</UserName>
<ParentAlbumFK xsi:nil="true" />
<DateCreated>2012-03-12T19:47:54.493</DateCreated>
</Album>
</ArrayOfAlbum>
And
[{"AlbumPK":"f09d14cf-3bab-44c8-b614-2b7cf728efd4","Name":"Colorado",
"UserName":"emorin","ParentAlbumFK":null,
"DateCr‌​eated":"2012-03-12T19:47:54.493"}]
Response from Fiddler changing the accept header to JSON.
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 17 Apr 2012 19:45:47 GMT
97
[{ "AlbumPK":"f09d14cf-3bab-44c8-614-2b7cf728efd4","Name":"Colorado",
"UserName":"emorin","ParentAlbumFK":null,
"DateCreated":"2012-03-12T19:47:54.493"}]
0
It seems that your server is sending data in the chunked encoding and perhaps the MonoDroid is having problem understanding chunked encoding. Try turning it off in IIS.

gzip compression with action filter not working

I am using a actionfilter to gzip compress my responses from actions inside controlers
This is my action filter:
Public Class CompressAttribute
Inherits ActionFilterAttribute
Implements IActionFilter
Public Overrides Sub OnActionExecuting(filterContext As ActionExecutingContext)
Dim request As HttpRequestBase = filterContext.HttpContext.Request
Dim acceptEncoding As String = request.Headers("Accept-Encoding")
If String.IsNullOrEmpty(acceptEncoding) Then
Return
End If
acceptEncoding = acceptEncoding.ToUpperInvariant()
Dim response As HttpResponseBase = filterContext.HttpContext.Response
If acceptEncoding.Contains("DEFLATE") Then
response.AppendHeader("Content-encoding", "deflate")
response.AppendHeader("Vary", "Accept-Encoding")
response.Filter = New WebCompressionFilter(response.Filter, CompressionMode.Compress)
ElseIf acceptEncoding.Contains("GZIP") Then
response.AppendHeader("Content-encoding", "gzip")
response.AppendHeader("Vary", "Accept-Encoding")
response.Filter = New WebCompressionFilter(response.Filter, CompressionMode.Compress)
End If
End Sub
End Class
I apply it to the actions inside my controlers.
The problem is that it works just fine on my desktop in development environment but on my live server (in shared hosting) it does not gzip encode.
Instead it does chunked transfer encoding....
Why?
this is my responses:
development environment:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Sun, 25 Mar 2012 04:12:29 GMT
X-AspNet-Version: 4.0.30319
p3p: CP=\'NOI ADM DEV PSAi COM NAV OUR OTR STP IND DEM\'
X-AspNetMvc-Version: 3.0
Content-Encoding: gzip
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 13411
Connection: Close
live server:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
p3p: CP=\'NOI ADM DEV PSAi COM NAV OUR OTR STP IND DEM\'
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 25 Mar 2012 04:13:09 GMT
Transfer-Encoding: chunked
X-OSSProxy: OSSProxy 1.3.331.322 (Build 331.322 Win32 en-us)(Oct 11 2011 17:53:42)
Connection: close
Is there any reason why you are trying to do this manually in your own code? This functionality already exists in IIS:
Make sure you have installed Dynamic Content Compression on the machine (bullet 5 in the link) and enabled it in IIS. I have never had any issues with it once these steps are completed. Once you do this there is also no need to have your attribute anymore, IIS will handle it for you implicitly on both static and dynamic content. Less code to maintain is always a good thing!

Resources