Splunk integration with Oozie - oozie

We need to capture Oozie workflow Failure events in Splunk - HTTP Event Collector (Example: https://qa.splunk.organization.com/services/collector).
To achieve this, we created a separate Oozie Java action to log the failure event to Splunk. The problem with this approach is, we have more than 100 oozie workflows and adding a new workflow action for Splunk is not feasible.
Is there any better approach to capture Oozie workflow failure in Splunk HTTP Event Collector?
Workflow.xml
<start to="Input_Check" />
<decision name="Input_Check">
<switch>
<case to="Input_Move"> ${fs:dirSize(source_hdfs_path) gt 0} </case>
<default to="end"/>
</switch>
</decision>
<action name="Input_Move">
<java>
<main-class>com.org.FileMove</main-class>
<arg>${source_hdfs_path}/</arg>
<arg>${destination_hdfs_path}</arg>
</java>
<ok to="Process_File" />
<error to="Splunk_Log" />
</action>
<action name="Process_File">
<java>
<main-class>com.org.FileProcessor</main-class>
<arg>inputPath=${destination_hdfs_path}/</arg>
<arg>outputPath=${output_hdfs_path}/</arg>
</java>
<ok to="end" />
<error to="Splunk_Log" />
</action>
<action name="Splunk_Log">
<java>
<main-class>com.org.SplunkLog</main-class>
<arg>https://qa.splunk.organization.com/services/collector</arg>
<arg>auth-token</arg>
<arg>Workflow Failed</arg>
</java>
<ok to="fail"/>
<error to="fail"/>
</action>
<kill name="fail">
<message>Test Splunk Workflow failed</message>
</kill>
<end name="end" />
</workflow-app>
Java Class
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class SplunkLog {
public static void main(String[] args) throws Exception {
if(args.length!=3){
System.exit(-1);
}
String URL = args[0];
String authToken = args[1];
String data = args[2];
String jsonData = "{\"event\": \"" + data + "\", \"sourcetype\": \"manual\"}";
URL url = new URL (URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestProperty ("Authorization", "Splunk " + authToken);
connection.setRequestMethod("POST");
connection.connect();
OutputStream outputStream = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(jsonData);
writer.close();
outputStream.close();
if (connection.getResponseCode()==HttpURLConnection.HTTP_OK) {
System.out.println("SUCCESS");
}else{
System.out.println("data : " + jsonData + "token : " + authToken);
System.out.println("ERROR : " + connection.getResponseMessage());
}
}
}

Related

Active directory Invalid token in xamarin forms

I am developing a small application using Xamarin forms, I would like to implement (MSAL) active directory, I have configured everything and getting token, after that I have checked in postman while I am getting below
{"success": false," message": "Sorry, you are not authorized to access this API. Please make sure you are logged in!","data":null}
I tried sending the web request to server while I am getting HTTP response below
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers: { Transfer-Encoding: chunked Server: Kestrel WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid" X-Rate-Limit-Limit: 12h X-Rate-Limit-Remaining: 4999 X-Rate-Limit-Reset: 2021-07-19T14:20:05.8546118Z Date: Mon, 19 Jul 2021 02:20:05 GMT Content-Type: text/plain }}
Here I tried the code below, please help me to resolve this issue
App.xaml.cs
public static IPublicClientApplication PCA = null;
public static string[] Scopes = { "User.Read" };
PCA = PublicClientApplicationBuilder.Create(Constants.ClientID)
.WithRedirectUri($"msauth://{Constants.AppId}/{Constants.SIGNATURE_HASH}")
.WithAuthority($"https://login.microsoftonline.com/{Constants.TenentID}")
.Build();
Viewmodel signin command i called SignInAsync
public async Task SignInAsync()
{
Microsoft.Identity.Client.AuthenticationResult authResult = null;
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync().ConfigureAwait(false);
try
{
IAccount firstAccount = accounts.FirstOrDefault();
authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
.ExecuteAsync();
Session.Instance.TokenValueFromApp = authResult.AccessToken;
}
catch (MsalUiRequiredException)
{
try
{
authResult = await App.PCA.AcquireTokenInteractive(App.Scopes) .WithParentActivityOrWindow(App.ParentWindow)
.ExecuteAsync();
Session.Instance.TokenValueFromApp = authResult.AccessToken;
}
catch (Exception ex2)
{
}
}
}
Mainactivity.cs
App.ParentWindow = this;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
Manifest.xml
<application android:label="#string/app_name" android:icon="#mipmap/icon">
<activity android:name="microsoft.identity.client.BrowserTabActivity" android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msal{clientid}" android:host="auth" /> //here i am pasting client id
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msauth" android:host="{bundleid}" android:path="/{signaturehash}" /> //here i am pasting bundle id and signature hash
</intent-filter>
</activity>
</application>
<queries>
<package android:name="com.azure.authenticator" />
<package android:name="{bundle id}" /> // here i am pasting a bundle id
<package android:name="com.microsoft.windowsintune.companyportal" />
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>

log4net:ERROR Could not create Appender [Console] of type [log4net.Appender.ColoredConsoleAppender]. Reported error

Hello friend I have the following problem when trying to use log4net in net core in my console application.
My code is this:
using log4net;
using log4net.Config;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Teltonika.Codec;
namespace UdpListener
{
class Program
{
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
static void Main()
{
XmlConfigurator.Configure();
IPAddress ip;
if (!IPAddress.TryParse(ConfigurationManager.AppSettings["ipAddress"], out ip))
{
Log.Error("Ip is not valid.");
throw new ArgumentException("Ip is not valid.");
}
int port;
if (!int.TryParse(ConfigurationManager.AppSettings["port"], out port))
{
Log.Error("Port is not valid.");
throw new ArgumentException("Port is not valid.");
}
Task.Run(async () =>
{
try
{
using (var udpClient = new UdpClient(new IPEndPoint(ip, port)))
{
Log.Info("Listening...");
while (true)
{
//IPEndPoint object will allow us to read datagrams sent from any source.
var receivedResults = await udpClient.ReceiveAsync();
byte[] data = receivedResults.Buffer;
//tramaService.InsertTrama(new Entity.GpsPuntos()
//{
// Fecha = DateTime.Now,
// Trama = String.Join("", data.Select(x => x.ToString("X2")).ToArray())
//});
Log.Info(string.Format("Received connection from: {0}", receivedResults.RemoteEndPoint));
Log.Info(string.Format("{0} - received [{1}]", DateTime.Now, String.Join("", data.Select(x => x.ToString("X2")).ToArray())));
var reader = new ReverseBinaryReader(new MemoryStream(data));
// Decode data
var avlData = new DataDecoder(reader).DecodeUdpData();
// Create response
var bytes = new List<byte>();
const short packetLength = 2 /* Id */+ 1 /* Type */ + 1 /* Avl packet id */+ 1 /* num of accepted elems */;
bytes.AddRange(BitConverter.GetBytes(BytesSwapper.Swap(packetLength)));
bytes.AddRange(BitConverter.GetBytes(BytesSwapper.Swap(avlData.PacketId)));
bytes.Add(avlData.PacketType);
bytes.Add(avlData.AvlPacketId);
bytes.Add((byte)avlData.AvlData.DataCount);
var response = bytes.ToArray();
Log.Info(string.Format("{0} - response [{1}]", DateTime.Now, String.Join("", bytes.Select(x => x.ToString("X2")).ToArray())));
await udpClient.SendAsync(response, response.Length, receivedResults.RemoteEndPoint);
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
});
Console.ReadLine();
}
}
}
this my mistake
log4net:ERROR Could not create Appender [Console] of type [log4net.Appender.ColoredConsoleAppender]. Reported error follows.
System.NotSupportedException: No data is available for encoding 850. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
at System.Text.Encoding.GetEncoding(Int32 codepage)
at log4net.Appender.ColoredConsoleAppender.ActivateOptions()
at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(XmlElement appenderElement)
log4net:ERROR Appender named [Console] not found.
My archive configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<appSettings>
<add key="ipAddress" value="172.17.160.1"/>
<add key="port" value="3316"/>
<!--<add key="log4net.Internal.Debug" value="true"/>-->
</appSettings>
<log4net>
<appender name="Console" type="log4net.Appender.ColoredConsoleAppender" Target="Console.Error">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger - %message%newline"/>
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="500KB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
</configuration>
I want it to show me in the console application that it is working.
I had this same error myself today after upgrading from .NET Framework to .NET 5. I managed to get around it by adding the following line at the start of my progam:
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
For me this was solved by using the ManagedColoredConsoleAppender instead.
Using the ManagedColoredConsoleAppender is a better solution if you want to run the application also on other OS's besides Windows.
The ColoredConsoleAppender depends on the kernel32.dll, which ManagedColoredConsoleAppender does not.
See also https://issues.apache.org/jira/browse/LOG4NET-658.

Invalid provider type specified when trying to access google analytics

We keep getting the error below whenever we try to access the API to get current user numbers. I've tried a few things but cannot get to the bottom of this. Can anyone shed any light on whats wrong/missing?
I should point out that thus runs perfectly fine on my local PC but is failing on the server.
Here is the error:
ConnectToAnalytics error:
System.Security.Cryptography.CryptographicException: Invalid provider
type specified. at
System.Security.Cryptography.Utils.CreateProvHandle(CspParameters
parameters, Boolean randomKeyContainer) at
System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType
keyType, CspParameters parameters, Boolean randomKeyContainer, Int32
dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle&
safeKeyHandle) at
System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at
System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32
dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) at
System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at
Google.Apis.Auth.OAuth2.ServiceAccountCredential.Initializer.FromCertificate(X509Certificate2
certificate) in
C:\Users\mdril\Documents\GitHub\google-api-dotnet-client\Src\GoogleApis.Auth.DotNet4\OAuth2\ServiceAccountCredential.cs:line
100 at Core.ConnectToAnalytics()
This error is thrown when i run the code:
Public Shared Function GetRealtimeUsers() As String
Try
'realtime on site
Dim gsService As AnalyticsService = Core.ConnectToAnalytics
Dim RequestRealtime As DataResource.RealtimeResource.GetRequest = gsService.Data.Realtime.[Get]([String].Format("ga:{0}", "xxxxx"), "rt:activeUsers")
Dim feed As RealtimeData = RequestRealtime.Execute()
Return Int(feed.Rows(0)(0)).ToString()
Catch ex As Exception
Return "QUOTA USED"
End Try
It error's here: RequestRealtime.Execute()
For reference - here's the connect script:
Public Shared Function ConnectToAnalytics() As AnalyticsService
Try
Dim scopes As String() = New String() {AnalyticsService.Scope.Analytics, AnalyticsService.Scope.AnalyticsEdit, AnalyticsService.Scope.AnalyticsManageUsers, AnalyticsService.Scope.AnalyticsReadonly}
Dim keyFilePath = HttpContext.Current.Server.MapPath("\xxx.p12")
Dim serviceAccountEmail = "xxx"
Dim certificate = New X509Certificate2(keyFilePath, "xxxx", X509KeyStorageFlags.Exportable)
Dim credential = New ServiceAccountCredential(New ServiceAccountCredential.Initializer(serviceAccountEmail) With {.Scopes = scopes}.FromCertificate(certificate))
Return New AnalyticsService(New BaseClientService.Initializer() With {.HttpClientInitializer = credential, .ApplicationName = "Client for xxx"})
Catch ex As Exception
Core.SendAdminStatusReport("ConnectToAnalytics error: " & ex.ToString)
Throw ex
End Try
End Function
I found the fix for this in this post:
https://www.daimto.com/azure-with-service-accounts-in-c/
Changing this line
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
to
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
Fixed my issue
Its hard to know what your issue is without seeing your code but here is my code for service account authncation
/// <summary>
/// Authenticating to Google using a Service account
/// Documentation: https://developers.google.com/accounts/docs/OAuth2#serviceaccount
/// </summary>
/// <param name="serviceAccountEmail">From Google Developer console https://console.developers.google.com</param>
/// <param name="serviceAccountCredentialFilePath">Location of the .p12 or Json Service account key file downloaded from Google Developer console https://console.developers.google.com</param>
/// <returns>AnalyticsService used to make requests against the Analytics API</returns>
public static AnalyticsreportingService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
throw new Exception("Path to the service account credentials file is required.");
if (!File.Exists(serviceAccountCredentialFilePath))
throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
if (string.IsNullOrEmpty(serviceAccountEmail))
throw new Exception("ServiceAccountEmail is required.");
// For Json file
if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
{
GoogleCredential credential;
using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
}
// Create the Analytics service.
return new AnalyticsreportingService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Analyticsreporting Service account Authentication Sample",
});
}
else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
{ // If its a P12 file
var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));
// Create the Analyticsreporting service.
return new AnalyticsreportingService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Analyticsreporting Authentication Sample",
});
}
else
{
throw new Exception("Unsupported Service accounts credentials.");
}
}
catch (Exception ex)
{
throw new Exception("CreateServiceAccountAnalyticsreportingFailed", ex);
}
}
}
Code ripped from ServiceAccount.cs
I managed to fix this - i was on the right lines with root certificates, turns out i was missing one. These can be found here:
https://pki.goog/
I cannot remember where i found this but adding the code below to the webconfig helped me figure out which certificate i was missing:
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.Net">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.HttpListener">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add
name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log"
traceOutputOptions = "ProcessId, DateTime"
/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
<add name="System.Net.Cache" value="Verbose" />
<add name="System.Net.HttpListener" value="Verbose" />
</switches>

Compress filter at the action level for ASP.NET Core MVC

I'm migrating an ASP.NET MVC 5 application to ASP.NET Core 2.1. In the "old" application I had a Compress filter that was apply Gzip to the response of specific requests. That way I was able to compress only specific requests and not all the requests.
Based on what I understand, ASP.NET Core has a different approach using middlewares and it only gives you the chance to apply compression to all the requests (adding it to the pipeline) or not applying it at all.
Is there a way to achieve what I want by creating an ActionFilterAttribute? this was my old code:
public class CompressAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var acceptEncoding = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding))
return;
acceptEncoding = acceptEncoding.ToLower();
var response = filterContext.HttpContext.Response;
if (acceptEncoding.Contains("gzip"))
{
response.AppendHeader("Content-Encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("deflate"))
{
response.AppendHeader("Content-Encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
}
}
I also had task for compressing responses only for some specific actions/controllers
Finally I've found a solution based on ActionFilterAttribute. here is an example
namespace CommonWebApi.MiddleWare
{
/// <summary>
/// Attribute for enabling Brotli/GZip/Deflate compression for specied action
/// </summary>
public class ResponseCompressionAttribute : ActionFilterAttribute
{
private Stream _originStream = null;
private MemoryStream _ms = null;
public override void OnActionExecuting(ActionExecutingContext context)
{
HttpRequest request = context.HttpContext.Request;
string acceptEncoding = request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding)) return;
acceptEncoding = acceptEncoding.ToUpperInvariant();
HttpResponse response = context.HttpContext.Response;
if (acceptEncoding.Contains("BR", StringComparison.OrdinalIgnoreCase))//Brotli
{
if (!(response.Body is BrotliStream))// avoid twice compression.
{
_originStream = response.Body;
_ms = new MemoryStream();
response.Headers.Add("Content-encoding", "br");
response.Body = new BrotliStream(_ms, CompressionLevel.Optimal);
}
}
else if (acceptEncoding.Contains("GZIP", StringComparison.OrdinalIgnoreCase))
{
if (!(response.Body is GZipStream))
{
_originStream = response.Body;
_ms = new MemoryStream();
response.Headers.Add("Content-Encoding", "gzip");
response.Body = new GZipStream(_ms, CompressionLevel.Optimal);
}
}
else if (acceptEncoding.Contains("DEFLATE", StringComparison.OrdinalIgnoreCase))
{
if (!(response.Body is DeflateStream))
{
_originStream = response.Body;
_ms = new MemoryStream();
response.Headers.Add("Content-encoding", "deflate");
response.Body = new DeflateStream(_ms, CompressionLevel.Optimal);
}
}
base.OnActionExecuting(context);
}
public override async void OnResultExecuted(ResultExecutedContext context)
{
if ((_originStream != null) && (_ms != null))
{
HttpResponse response = context.HttpContext.Response;
await response.Body.FlushAsync();
_ms.Seek(0, SeekOrigin.Begin);
response.Headers.ContentLength = _ms.Length;
await _ms.CopyToAsync(_originStream);
response.Body.Dispose();
_ms.Dispose();
response.Body = _originStream;
}
base.OnResultExecuted(context);
}
}
}
known limitations/essentials:
MemoryStream is required only to get length of compressed stream. This value should be set to response.Headers.ContentLength for correct work.
currently it works only for 3 types of compression.
I found two different approaches to apply compression to specific scenarios:
1) Create a middleware and analyze the request before applying compression. I did not like this approach because the middleware would run for all the requests and would have to examine the request information, affecting the performance.
2) Modify the Web.config file (this is the approach I took) and apply compression to certain dynamic and static types. When an ASP.NET Core app is published, a web.config is automatically generated. We can edit the web.config file and add compression like I did in the following example:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<urlCompression doStaticCompression="true" doDynamicCompression="true" />
<httpCompression>
<dynamicTypes>
<clear />
<add enabled="true" mimeType="text/*" />
<add enabled="true" mimeType="message/*" />
<add enabled="true" mimeType="application/x-javascript" />
<add enabled="true" mimeType="application/javascript" />
<add enabled="true" mimeType="application/json" />
<add enabled="false" mimeType="*/*" />
<add enabled="true" mimeType="application/atom+xml" />
<add enabled="true" mimeType="application/atom+xml;charset=utf-8" />
</dynamicTypes>
<staticTypes>
<clear />
<add enabled="true" mimeType="text/*" />
<add enabled="true" mimeType="message/*" />
<add enabled="true" mimeType="application/javascript" />
<add enabled="true" mimeType="application/atom+xml" />
<add enabled="true" mimeType="application/xaml+xml" />
<add enabled="false" mimeType="*/*" />
</staticTypes>
</httpCompression>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\YourApplicationName.dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" />
</system.webServer>
</configuration>

WCF restful service access denied when trying to upload file?

I made a WCF restful service for uploading the files to specific directory on the server, and a small ASP.NET web application that can upload the files threw this web service. The problem is that I am constantly getting the error of access denied. I tried to give all the privileges to a folder for testing purposes (Full control for Everyone, Full control for IIS_IUSRS, AppPool of WCF and Web service, etc.), but still the same error shows. Below is the code of Service and Web application:
Main WCF service class
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerCall,
IgnoreExtensionDataObject = true,
IncludeExceptionDetailInFaults = true)]
public class UploadFile : IUploadFile
{
public ReturnValue ExcelUpload(Stream File)
{
using (FileStream writer = new FileStream(#"C:\Users\Public\Documents", FileMode.Create))
{
int ReadCount = 0;
var buffer = new byte[8192];
while ((ReadCount = File.Read(buffer, 0, buffer.Length)) != 0)
{
writer.Write(buffer, 0, ReadCount);
}
}
return new ReturnValue() { IsSuccessfull = true };
}
public ReturnValue test(int id)
{
return new ReturnValue() { IsSuccessfull = true };
}
}
WCF service contract
[ServiceContract(Name = "ExcelUpload.IUploadFile")]
public interface IUploadFile
{
[OperationContract]
[DataContractFormat]
[WebInvoke(Method = "*",
UriTemplate = "UploadExcel/",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json)]
ReturnValue ExcelUpload(Stream File);
// TODO: Add your service operations here
[OperationContract]
[DataContractFormat]
[WebInvoke(Method = "POST",
UriTemplate = "test/",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json)]
ReturnValue test(int id);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class ReturnValue
{
[DataMember]
public bool IsSuccessfull { get; set; }
}
WCF service web.config
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="~/UploadFile.svc" service="ExcelUpload.UploadFile"/>
</serviceActivations>
</serviceHostingEnvironment>
<bindings>
<webHttpBinding>
<binding name="crossDomain"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
transferMode="Streamed"
sendTimeout="00:05:00"
crossDomainScriptAccessEnabled="true">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="defaultServiceBehaviour">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="100" maxConcurrentInstances="100" maxConcurrentSessions="100"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="defaultEndpointBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="ExcelUpload.UploadFile" behaviorConfiguration="defaultServiceBehaviour">
<endpoint address="" behaviorConfiguration="defaultEndpointBehaviour" bindingConfiguration="crossDomain" binding="webHttpBinding" contract="ExcelUpload.IUploadFile"></endpoint>
</service>
</services>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="basicHttpBinding" scheme="http"/>
</protocolMapping>
</system.serviceModel>
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
</authentication>
<requestFiltering allowHighBitCharacters="true">
<verbs allowUnlisted="false">
<add verb="POST" allowed="true"/>
<add verb="GET" allowed="true"/>
</verbs>
</requestFiltering>
</security>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Web application
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="UploadTest.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Uploading using WCF REST API</title>
<script type="text/javascript">
function uploadBlobOrFile(blobOrFile) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://intranet-services.tosama.si/CroSalesExcelUpload/UploadFile.svc/UploadExcel/', true);
xhr.setRequestHeader('Content-length', blobOrFile.size);
xhr.onload = function (e) {
progressBar.value = 0;
progressBar.textContent = progressBar.value;
};
// Listen to the upload progress.
var progressBar = document.querySelector('progress');
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
progressBar.value = (e.loaded / e.total) * 100;
progressBar.textContent = progressBar.value; // Fallback.
}
};
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
xhr.send(blobOrFile);
}
</script>
</head>
<body>
<input id="filePicker" type="file" name="Package" accept="image/*"/>
<br />
<progress min="0" max="100" value="0">0% complete</progress>
<br />
<button title="upload"
onclick="if (filePicker.files[0]) uploadBlobOrFile(filePicker.files[0])">
<span>Upload</span>
</button>
</body>
</html>
Very basic thing is, why are you trying to create object for directory?
#"C:\Users\Public\Documents"
try changing to #"C:\Users\Public\Documents\MyFile.txt"
Here you can use any type of file instead of txt.
And don't forget to set limits for your file to be uploaded.
Hope it helps.. !

Resources