Send Very big string data in HTTPPost request - asp.net-web-api

I have a requirement to encode the file data into base64 encoding and upload the file, This works completely fine if the file size is less than 2-3KB when i try sending relatively big files it throws 403 error(Remote Server returned an error: (403) Forbidden), There is no issue with authentication it is successfully established.
Below is the code snippet I am using to make request
Public Shared Function PostData() As String
Dim sReturnValue As String = String.Empty
Dim sUrl As String = http://localhost:50562/API/UploadFile/UploadSingleFile
Dim oRequest As HttpWebRequest
Dim oResponse As HttpWebResponse
oRequest = TryCast(WebRequest.Create(sUrl), HttpWebRequest)
oRequest.AllowWriteStreamBuffering = True
oRequest.Method = "POST"
oRequest.ContentType = "text/json"
oRequest.Headers.Add("Accept-Language", "en-us")
If m_bPassKeyInHeader = True Then
oRequest.Headers.Add("APIKey", m_sAPIKey)
End If
If i_sData IsNot Nothing AndAlso i_sData.Length > 0 Then
Using oWriter As New StreamWriter(oRequest.GetRequestStream())
oWriter.Write(i_sData)
End Using
End If
Try
oResponse = oRequest.GetResponse()
Catch ex As Exception
End Try
Using oReader As New StreamReader(oResponse.GetResponseStream())
sReturnValue = oReader.ReadToEnd()
End Using
Return sReturnValue
I am not sending the file as multipart/formdata as my requirement needs the file data to be encoded, what change should i make to get this working.

Try increasing your maxRequestLength and maxAllowedContentLength in the web.config:
<system.web>
<httpRuntime targetFramework="4.6.2" maxRequestLength="1048576" />
</system.web>
...
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>
Which gets priority, maxRequestLength or maxAllowedContentLength?

Related

Can i use multiple method type put on godaddy server?

I Use two method type put in web-api.It is correct in localhost.but when i use this on godaddy server it is incorrect and i have error 405.
[RoutePrefix("api/MyController")]
public class MyController : ApiController
{
[HttpPut]
[Route("Method1")]
public returnObject Method1([FromBody]object1 object)
{
return returnObject1
}
[HttpPut]
[Route("Method2")]
public returnObject2 Method2([FromBody]object2 object)
{
return returnObject2
}
}
But i dont access to applicationhost.config in godaddy server however i try to add this section with this code in my project.
using (ServerManager serverManager = new ServerManager())
{
Configuration configAdmin = serverManager.GetApplicationHostConfiguration();
var section = configAdmin.GetSection("system.webServer/modules", "");
var collection = section.GetCollection();
var element = collection.CreateElement();
element.Attributes["name"].Value = "ExtensionlessUrl-Integrated-4.0";
element.Attributes["path"].Value = "*.";
element.Attributes["verb"].Value = "GET,HEAD,POST,DEBUG";
element.Attributes["type"].Value = "System.Web.Handlers.TransferRequestHandler";
element.Attributes["preCondition"].Value = "integratedMode,runtimeVersionv4.0";
collection.Add(element);
serverManager.CommitChanges();
}
when i run project and run up to line element.Attributes["path"] this is null and i have error.
I solved my problem with the use of post method Instead of put method.
Thank you Ipsit Gaur
Just make sure PUT verb is enabled on IIS on GoDaddy server by checking applicationhost.config file's line
<add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
And simply adding PUT verb there as it is disabled by default.

Handle Ajax calls when user session expires

In my MVC 5 web application when the user session expires and the user clicks in something in the page that does an AJAX call I was still getting response status 200 with X-Responded-JSON:401.
I have then read and investigated and found a way to solve the problem.
So...added to the Startup class ConfigureAuth method this
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider =
new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(TimeSpan.FromMinutes(15), (manager, user) => user.GenerateUserIdentityAsync(manager)),
OnApplyRedirect = ctx =>
{
if (!IsAjaxRequest(ctx.Request))
{
ctx.Response.Redirect(ctx.RedirectUri);
}
}
},
SlidingExpiration = false,
ExpireTimeSpan = TimeSpan.FromMinutes(30)
});
Just a helper...
private static bool IsAjaxRequest(IOwinRequest request)
{
IReadableStringCollection query = request.Query;
if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
{
return true;
}
IHeaderDictionary headers = request.Headers;
return (headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest");
}
This solved my problem locally (in my dev machine) and I am now able to see the 401 in the Ajax calls when the sessions expires or the user logs or when is still trying to access something in a open tab.
My problem is that this work only locally. When I have my application in a server this Ajax calls still return 200 and I do not understand why....however if I access the application inside of the box everything works as expected and I can see the 401 in the browser
Can someone maybe know a better solution for this or maybe the reason why this works locally but not in the server?
Many thanks
The solution posted in the initial question works as expected. This approach was not working in the beginning because of the custom error pages that you can define in the web.config. It was messing up with the initial solution that I found in the web.
<system.web>
<globalization enableClientBasedCulture="true" culture="en-GB" uiCulture="auto" />
<customErrors mode="Off" defaultRedirect="~/Error/Index">
<error statusCode="400" redirect="~/Error/Index" />
<error statusCode="401" redirect="~/Error/Index" />
...
...
This was redirecting to a different page and because of that was returning 200 instead of 401.
Thanks

IIS Overwriting HTTP Response Text When HTTP Response Status set as 400

I am building an MVC 3 application with an IIS 7.5 backend. On my controller, I have action methods that allow the user to add/edit domain objects. The Action handles HTTP Post, has a return value of string which contains any validation error messages encountered during the save process. Here is an example of one Action Method:
[HttpPost]
public string CustomerEdit(CustomerModel customerModel)
{
var errorMessages = new StringBuilder();
var serverErrors = new List<string>();
//Map to a customer domain object
Mapper.CreateMap<CustomerModel, Customer>();
var customer = Mapper.Map<CustomerModel, Customer>(customerModel);
if (customerModel.Oper == "del")
{
var customerIds = new List<Guid>();
customerIds.Add(customer.Id);
if (!_serverService.DeleteCustomers(customerIds))
{
errorMessages.Append("The item could not be deleted");
Response.StatusCode = Constants.STATUS_SERVER_ERROR;
}
}
else
{
//Validate
if (!_serverService.ValidateCustomer(customer, out serverErrors))
{
foreach (var error in serverErrors)
{
ModelState.AddModelError("Validation", error);
}
}
//Save
if (ModelState.IsValid)
{
var saveStatus = _serverService.SaveCustomer(ref customer, _id);
if (!saveStatus)
{
errorMessages.Append("The server encountered and error during Save");
Response.StatusCode = Constants.STATUS_SERVER_ERROR;
}
}
else
{
errorMessages.Append(GetValidationErrors(ModelState));
Response.StatusCode = Constants.STATUS_SERVER_ERROR;
}
}
return errorMessages.ToString();
}
In the case of an error, I need to set the Response.StatusCode property to a value of either 400/500, and return a concatenated string of detailed error messages. Unfortunately, IIS always strips my error string out of the response test, and (in the case of 400 errors) adds replaces it with the string 'Bad Request'
Is there a way to configure IIS to return a custom, Action-specific, string when the status code is set to 400?
After talking to a friend of mine who is a wiz at configuring IIS, I found that in IIS 7+ you can add the following to web.config:
<system.webServer>
<httpErrors errorMode="Detailed"/>
</system.webServer>
If this setting in web.config is used, AND you set the body of the response, then the response body will reach the client. If you do NOT set the response body, then IIS will serve up a detailed error page with detailed error information (see http://learn.iis.net/page.aspx/267/how-to-use-http-detailed-errors-in-iis/). Many folks consider this a security risk, so use with caution.
In MVC it is also possible to do this on a Action by Action basis. See TrySkipisCustomErrors.
Use:
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return this.Json(SomeJsonObject); // could output string too
we ended up with going for
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="PassThrough" />
</system.webServer>
in the web.config. Which allowed custom errors that set status codes to leave IIS unmolested.
At least the page Configuring HTTP Error Responses in IIS 7 says
Note
You cannot customize the following HTTP error messages: 400,
403.9, 411, 414, 500, 500.11, 500.14, 500.15, 501, 503, and 505.
EDIT: though in the responses of this question, which looks quite similar, there is a response claiming that at least something can be done with httpErrors configuration.

Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive

I am getting this error in my .net(Azure) application:-
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive...
I am rewritting the URL(am using server.transfer for this)
When I access the page directly or with a Response.Redirect, there is no error.
Any idea?
I am using below code.
Public Class URLRewriter
Implements IHttpModule
Public Sub Init(ByVal inst As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
AddHandler inst.BeginRequest, AddressOf Me.OnBeginRequest
End Sub
Public Sub OnBeginRequest(ByVal app As Object, ByVal e As EventArgs)
Dim inst As HttpApplication = CType(app, HttpApplication)
Dim req_path As String = inst.Context.Request.Path
Dim trans_path As String = ""
Select Case req_path.ToLower()
Case "/firstpage"
trans_path = "/Default.aspx"
Case "/secondpage"
trans_path = "/About.aspx"
Case "/testapp"
trans_path = "/Test/Test1.aspx"
Case Else
trans_path = "/"
End Select
If Not trans_path = "/" Then
inst.Context.Server.Transfer(trans_path)
End If
End Sub
End Class
In web.config I added this tag under httpModules also:-
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="URLRewriter" type="URLRewriter"/>
<add type="System.Web.SessionState.SessionStateModule" name="Session" />
after adding above code in my azure application url rewrite is working fine, but when I try to use session its giving me error(Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive.) means its lossing the session during url rewrite.

WP7 HttpWebRequest without caching

It seems that HttpWebRequest caching in WP7 is enabled by default, how do I turn it off?
Adding a random
param url + "?param=" + RND.Next(10000) works, but it's quite tricky and I'm not sure if it will work
with all servers.
For future reference , this worked for me ( I could not use additional query parameter due to project requirements) :
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
if (request.Headers == null)
{
request.Headers = new WebHeaderCollection();
}
request.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString();
In case of HttpClient (Portable for Windows Phone) "Cache-Control": "no-cache" on server side works only sometimes. And I cannot add query string random value to RESTful api call as well.
Solution from #frno works good and looks like for HttpClient:
client.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow;
Thank you.
How do you know it's the phone, not the server (or a proxy somewhere between) which is caching?
Have you checked this with Fiddler2 (or equivalent)?
Have you tried setting headers to disable caching?
Something like:
myRequest = (HttpWebRequest)WebRequest.Create(myUri);
myRequest.Headers["Cache-Control"] = "no-cache";
myRequest.Headers["Pragma"] = "no-cache";
We've seen the same behaviour with Silverlight hosted in Chrome.
We add a "?nocache=" + DateTime.Now.Ticks.ToString() to our request URLs if we want to prevent caching.
I found 3 ways
Add a random Query String to the end of your URI (think Guid.NewGuid()) this will avoid caching on the client as the Query String will be different each time
string uri = "http://host.com/path?cache="+Guid.NewGuid().ToString();
Specify no cache in the OutgoingResponse header within your WCF service operation:
var __request = (HttpWebRequest)WebRequest.Create(url.ToString());
if (__request.Headers == null)
__request.Headers = new WebHeaderCollection();
__request.Headers.Add("Cache-Control", "no-cache");
markup your service operation with the AspNetCacheProfile attribute:
[AspNetCacheProfile("GetContent")]
public ResultABC GetContent(string abc)
{
__request = (HttpWebRequest)WebRequest.Create(abc);
return __request;
}
And update your web.config
<system.web>
<caching>
<outputCache enableOutputCache="true" />
<outputCacheSettings>
<outputCacheProfiles >
<add name="GetContent" duration="0" noStore="true" location="Client" varyByParam="" enabled="true"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
...
</system.web>
Adding random number is not bad and it will work. I have used Time (in ajax call). Was placed in the url like a folder.
Yes is possible... :) I spend one week of Experiment and the answer is really simple :
HttpWebRequest _webRequest = WebRequest.CreateHttp(_currentUrl);
_webRequest.AllowReadStreamBuffering = false
_webRequest.BeginGetResponse(_onDownload,
userState);

Resources