Xolani Christopher Xolani Christopher - 1 month ago 25
C# Question

YouTube Data API v3 doesn't work when deployed on production server

I want to create a Stream and live broadcast it. The code works very fine on the localhost but when deployed it's a problem. It doesn't even request for Authorization on the Google account. Looks like it doesn't even interact with it.


Server Error in '/123456' Application.

Access to the path 'YouTubeDataAPISample.YouTube.Auth.Store' is
denied.

Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.

Exception Details: System.UnauthorizedAccessException: Access to the
path 'YouTubeDataAPISample.YouTube.Auth.Store' is denied.

ASP.NET is not authorized to access the requested resource. Consider
granting access rights to the resource to the ASP.NET request
identity. ASP.NET has a base process identity (typically
{MACHINE}\ASPNET on IIS 5 or Network Service on IIS 6 and IIS 7, and
the configured application pool identity on IIS 7.5) that is used if
the application is not impersonating. If the application is
impersonating via , the identity will be
the anonymous user (typically IUSR_MACHINENAME) or the authenticated
request user.

To grant ASP.NET access to a file, right-click the file in File
Explorer, choose "Properties" and select the Security tab. Click "Add"
to add the appropriate user or group. Highlight the ASP.NET account,
and check the boxes for the desired access.

Source Error:

An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.

Stack Trace:

[UnauthorizedAccessException: Access to the path
'YouTubeDataAPISample.YouTube.Auth.Store' is denied.]

System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
+217 System.IO.Directory.InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, Boolean checkHost) +11130032

System.IO.Directory.InternalCreateDirectoryHelper(String path, Boolean
checkHost) +136 System.IO.Directory.CreateDirectory(String path)
+33 Google.Apis.Util.Store.FileDataStore..ctor(String folder, Boolean fullPath) +72

Template.BusinessLogic.Implementation.YouTubeAPI.AuthenticateOauth(String
clientId, String clientSecret, String userName, String apiKey) +220

Template.BusinessLogic.Implementation.YouTubeAPI..ctor() +63

Template.MVC5.Controllers.VideosController..ctor() +25

[TargetInvocationException: Exception has been thrown by the target of
an invocation.] System.RuntimeTypeHandle.CreateInstance(RuntimeType
type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached,
RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0

System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean
skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113

System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,
Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
+232 System.Activator.CreateInstance(Type type, Boolean nonPublic) +83 System.Activator.CreateInstance(Type type) +66 System.Web.Mvc.DefaultControllerActivator.Create(RequestContext
requestContext, Type controllerType) +55

[InvalidOperationException: An error occurred when trying to create a
controller of type 'Template.MVC5.Controllers.VideosController'. Make
sure that the controller has a parameterless public constructor.]

System.Web.Mvc.DefaultControllerActivator.Create(RequestContext
requestContext, Type controllerType) +178

System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext
requestContext, Type controllerType) +77

System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext
requestContext, String controllerName) +88

System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase
httpContext, IController& controller, IControllerFactory& factory)
+191 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50

System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext,
AsyncCallback callback, Object state) +48

System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext
context, AsyncCallback cb, Object extraData) +16

System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+301 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155


Authorization Code

private static YouTubeService AuthenticateOauth(string clientId, string clientSecret, string userName, string apiKey)
{
string[] scopes = new string[] { YouTubeService.Scope.Youtube, // view and manage your YouTube account
YouTubeService.Scope.YoutubeForceSsl,
YouTubeService.Scope.Youtubepartner,
YouTubeService.Scope.YoutubepartnerChannelAudit,
YouTubeService.Scope.YoutubeReadonly,
YouTubeService.Scope.YoutubeUpload};


// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, new FileDataStore("YouTubeDataAPISample.YouTube.Auth.Store")).Result;

YouTubeService service = new YouTubeService(new YouTubeService.Initializer()
{
ApiKey = apiKey,
HttpClientInitializer = credential,
ApplicationName = "YouTubeDataAPISample"
});

return service;
}


Code for retrieving videos

public PlaylistItemListResponse Videos()
{
var playlistItemsListRequest = service.PlaylistItems.List("snippet");

var channelsListRequest = service.Channels.List("contentDetails");
channelsListRequest.Mine = true;
foreach (var find in channelsListRequest.Execute().Items)
{
var uploadsListId = find.ContentDetails.RelatedPlaylists.Uploads;

var nextPageToken = "";
while (nextPageToken != null)
{

playlistItemsListRequest.PlaylistId = uploadsListId;
playlistItemsListRequest.MaxResults = 50;
playlistItemsListRequest.PageToken = nextPageToken;

// Retrieve the list of videos uploaded to the authenticated user's channel.
var playlistItemsListResponse = playlistItemsListRequest.Execute();

nextPageToken = playlistItemsListResponse.NextPageToken;
}
}
return playlistItemsListRequest.Execute();
}

Answer

To find the error you will have to do one of three things:

  1. Log onto the server and hit it on 'localhost' in order to see the detailed error information.
  2. Write some custom code to output logs to somewhere so you can read them.
  3. Disable customErrors as suggested in the error message you have. This is a bad idea, but it's your call. It should set to remoteonly.