I have some code from an older version (version 6) of umbraco that allows the user to choose an audio file and then insert a html 5 audio player into the page using a macro. I have copied this over to version 7 but it doesn't work. I keep getting this error :
Error loading Partial View script (file: ~/Views/MacroPartials/InsertAudio.cshtml)
Code :
#inherits umbraco.MacroEngines.DynamicNodeContext
#{
var controls = Parameter.controls;
var mp3Url = Library.NodeById(Parameter.mp3).Url;
string controlsTog = "";
if (controls == "1"){
controlsTog = "controls";
}
<audio #controlsTog>
<source src="#mp3Url" type="audio/mpeg" />
Your browser does not support the audio tag.
</audio>
}
You have to convert your legacy razor macro to a Partial View Macro. Here's a basic guide on how to perform the conversion:
https://our.umbraco.org/documentation/reference/templating/macros/Partial-View-Macros/
I've made the necessary changes to your script file but this is untested. I've also assumed that your MP3 is an item in the Media section so if this is incorrect you might have to replace Umbraco.TypedMedia with Umbraco.TypedContent.
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#{
var mp3Id = Model.MacroParameters["mp3"].ToString();
var mp3 = Umbraco.TypedMedia(mp3Id);
var mp3Url = mp3 != null ? mp3.Url : string.Empty;
var controlsTog = string.Empty;
if (string.Equals(Model.MacroParameters["controls"].ToString(), "1"))
{
controlsTog = "controls";
}
}
#if (!string.IsNullOrEmpty(mp3Url))
{
<audio #controlsTog>
<source src="#mp3Url" type="audio/mpeg" />
Your browser does not support the audio tag.
</audio>
}
Related
I am trying to get audio capture from the microphone working on Safari on iOS11 after support was recently added
However, the onaudioprocess callback is never called. Here's an example page:
<html>
<body>
<button onclick="doIt()">DoIt</button>
<ul id="logMessages">
</ul>
<script>
function debug(msg) {
if (typeof msg !== 'undefined') {
var logList = document.getElementById('logMessages');
var newLogItem = document.createElement('li');
if (typeof msg === 'function') {
msg = Function.prototype.toString(msg);
} else if (typeof msg !== 'string') {
msg = JSON.stringify(msg);
}
var newLogText = document.createTextNode(msg);
newLogItem.appendChild(newLogText);
logList.appendChild(newLogItem);
}
}
function doIt() {
var handleSuccess = function (stream) {
var context = new AudioContext();
var input = context.createMediaStreamSource(stream)
var processor = context.createScriptProcessor(1024, 1, 1);
input.connect(processor);
processor.connect(context.destination);
processor.onaudioprocess = function (e) {
// Do something with the data, i.e Convert this to WAV
debug(e.inputBuffer);
};
};
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(handleSuccess);
}
</script>
</body>
</html>
On most platforms, you will see items being added to the messages list as the onaudioprocess callback is called. However, on iOS, this callback is never called.
Is there something else that I should do to try and get it called on iOS 11 with Safari?
There are two problems. The main one is that Safari on iOS 11 seems to automatically suspend new AudioContext's that aren't created in response to a tap. You can resume() them, but only in response to a tap.
(Update: Chrome mobile also does this, and Chrome desktop will have the same limitation starting in version 70 / December 2018.)
So, you have to either create it before you get the MediaStream, or else get the user to tap again later.
The other issue with your code is that AudioContext is prefixed as webkitAudioContext in Safari.
Here's a working version:
<html>
<body>
<button onclick="beginAudioCapture()">Begin Audio Capture</button>
<script>
function beginAudioCapture() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var processor = context.createScriptProcessor(1024, 1, 1);
processor.connect(context.destination);
var handleSuccess = function (stream) {
var input = context.createMediaStreamSource(stream);
input.connect(processor);
var recievedAudio = false;
processor.onaudioprocess = function (e) {
// This will be called multiple times per second.
// The audio data will be in e.inputBuffer
if (!recievedAudio) {
recievedAudio = true;
console.log('got audio', e);
}
};
};
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(handleSuccess);
}
</script>
</body>
</html>
(You can set the onaudioprocess callback sooner, but then you get empty buffers until the user approves of microphone access.)
Oh, and one other iOS bug to watch out for: the Safari on iPod touch (as of iOS 12.1.1) reports that it does not have a microphone (it does). So, getUserMedia will incorrectly reject with an Error: Invalid constraint if you ask for audio there.
FYI: I maintain the microphone-stream package on npm that does this for you and provides the audio in a Node.js-style ReadableStream. It includes this fix, if you or anyone else would prefer to use that over the raw code.
Tried it on iOS 11.0.1, and unfortunately this problem still isn't fixed.
As a workaround, I wonder if it makes sense to replace the ScriptProcessor with a function that takes the steam data from a buffet and then processes it every x milliseconds. But that's a big change to the functionality.
Just wondering... do you have the setting enabled in Safari settings? It comes enabled by default in iOS11, but maybe you just disabled it without noticing.
When I first tested this code it seemed to work just fine, but now I am getting a bug.
Failed to load PDF document
I upload a pdf via my admin function, it goes into a database, and then I have an action in my controller that allows a person to download that pdf when it is clicked on.
However, it doesn't seem to work all the time. I also haven't been able to really identify what is causing it to break. If the file size is over 78 kb it seems that Chrome can't open the document while Firefox/Edge can. If the file is under 75 kb Chrome/IE opens it just fine. I am unsure of why this is happening.
I have included my controller below
public ActionResult DownloadPdf(int Id) {
var dbTest = _testRepository.FindId(Id);
var cd = new System.Net.Mime.ContentDisposition { FileName = dbTest.PdfName, Inline = true };
Response.AddHeader("Content-Disposition", cd.ToString());
return File(dbTest.PdfData, "application/pdf");
}
Here is my View
#if (Model.Test.HasPdf)
{
<a data-bind="css: { disabled: !form() }" href="#Url.Action("DownloadPdf", "Test", new { Id = Model.Test.Id })" target="_blank" id="launchBtn" class="btn btn-pdf">Download PDF Form</a>
}
Has anyone else ever had an error like this? If so, how did you fix it?
I figured it out. It had nothing to do with my download feature, it was in my HTTPPost
if (vm.FileData != null)
{
using (var stream = new System.IO.MemoryStream(vm.FileData.ContentLength\\This code between the parenthesis was missing))
{
vm.FileData.InputStream.CopyTo(stream);
test.FileData = stream.GetBuffer();
test.FileName = vm.FileData.FileName;
}
Supposing that your "dbTest" has a property with the PDF content as byte array (byte[]).
To direct download the file
public ActionResult DownloadPdf(int Id) {
var dbTest = _testRepository.FindId(Id);
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", $"filename={dbTest.PdfName}");
Response.AppendHeader("Content-Length", dbTest.PdfData.Length.ToString(CultureInfo.InvariantCulture));
Response.BinaryWrite(dbTest.PdfData);
Response.End();
return null;
}
or to open the file in a new browser tab
public ActionResult DownloadPdf(int Id) {
var dbTest = _testRepository.FindId(Id);
return File(dbTest.PdfData, "application/pdf", dbTest.PdfName);
}
I hope this helps you
Hi I need help from you - ASP.NET MVC.
In my web application, I have a html5 audio.
It works once, but when you refresh the page, this video is in the browser's memory.
When I refresh the page, it should hit new controller action, just like the first time.
Please look at my code below:
My View
<audio controls style="width: 400px;">
<source src="#Url.Action("StreamUploadedSong")" type="audio/mp3" />
Your browser does not support the audio element.
</audio>
My Controller
public FileStreamResult StreamUploadedSong() // <--------- Do not enter here the second time.
{
byte[] teste = null;
string query1 = "SELECT * FROM Video WHERE Id= '2'";
using (SqlConnection connection1 = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
using (SqlCommand command1 = new SqlCommand(query1, connection1))
{
connection1.Open();
var reader = command1.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
teste = (byte[])reader["Voice"];
}
connection1.Close();
}
long fSize = teste.Length;
long startbyte = 0;
long endbyte = fSize - 1;
int statusCode = 200;
if ((Request.Headers["Range"] != null))
{
//Get the actual byte range from the range header string, and set the starting byte.
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
startbyte = Convert.ToInt64(range[1]);
if (range.Length > 2 && range[2] != "") endbyte = Convert.ToInt64(range[2]);
//If the start byte is not equal to zero, that means the user is requesting partial content.
if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
{ statusCode = 206; }//Set the status code of the response to 206 (Partial Content) and add a content range header.
}
long desSize = endbyte - startbyte + 1;
//Headers
Response.StatusCode = statusCode;
Response.ContentType = "audio/mp3";
Response.AddHeader("Content-Accept", Response.ContentType);
Response.AddHeader("Content-Length", desSize.ToString());
Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}", startbyte, endbyte, fSize));
//Data
var stream = new MemoryStream(teste, (int)startbyte, (int)desSize);
return new FileStreamResult(stream, Response.ContentType);
}
Any idea how to refresh page to enter controller action StreamUploadedSong again?
I found solution !
Using Guid.NewGuid to Initializes a new instance of the Guid structure.
Bruce commented on this forum The Asp.net MVC:
"The browser caches the audio. If you want it to fetch every time, the URL should be unique. Just add a guid to the URL."
Source: ASP.NET Forums
Replace:
<source src="#Url.Action("StreamUploadedSong")" type="audio/mp3" />
to
<source src="#Url.Action("StreamUploadedSong", "Account", new {id = Guid.NewGuid()})" type="audio/mp3" />
I have problem playing local video on iOS on my Cordova based app. At the beginning I want to stress out that this problem is happening only when I'm using WKWebView, and if UiWebView is used, video plays fine. This is scenario I have:
-User comes to screen to which video url is passed
-Via FileTransfer I download it to phone and store it at desired location
-Using JS video is loaded to <video> tag and played.
Basically I'm doing everything as described in answer to this SO question.
The problem with UiWebView was that if relative path was set to src, video for some reason couldn't be loaded (no matter which combination I used), so this solution worked great for me, because it is based on this line of code:
entry.toURL()
This returns full path of the downloaded video which is great, at least for the UiWebView.
The problem for WkWebView is that entry.toURL() returns smth. like this:
file:///var/mobile/Containers/Data/Application/3A43AFB5-BEF6-4A0C-BBDB-FC7D2D98BEE9/Documents/videos/Dips.mp4
And WKWebView doesn't work with file:// protocol. Also, neither WKWebView works wit relative paths :(
Can anyone help me to fix this ?
I got this working today with the following but only when deployed to my device in Release mode. When deploying the app in Debug mode to my device it would not work.
iOS 9.3.2
Cordova 4.0.0 (iOS 3.8.0)
Telerik WKWebView Polyfill 0.6.9
Video list load method:
var path = window.cordova.file.documentsDirectory, //iTunes File Sharing directory
href = 'http://localhost:12344/Documents', //WKWebView default server url to documents
list = [];
function fsSuccess(dir) {
var reader = dir.createReader();
reader.readEntries(function (entries) {
for (var i = 0; i < entries.length; i++) {
list.push({ name: entries[i].name, path: href + entries[i].fullPath });
}
});
}
function fsError(error) {
console.log('error', error)
}
window.resolveLocalFileSystemURL(path, fsSuccess, fsError);
Video list click handler:
var video = $('#video')[0],
source = $('#source');
function play(index) {
source.attr('src', list[index].path);
video.load();
video.play();
}
Video player markup:
<video id="video" autoplay controls loop webkit-playsinline>
<source id="source" type="video/mp4" />
</video>
I was banging my head on my desk a la Ren Hoek while debugging until I attempted a release buid and it worked.
Sample snippet that uses cordova file opener plugin to open the download file from device.(Not tested in WKWebView though)
var fileTransfer = new FileTransfer();
var cdr;
if (sessionStorage.platform.toLowerCase() == "android") {
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, onFileSystemSuccess, onError);
} else {
// for iOS
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemSuccess, onError);
}
function onError(e) {
navigator.notification.alert("Error : Downloading Failed");
};
function onFileSystemSuccess(fileSystem) {
var entry = "";
if (sessionStorage.platform.toLowerCase() == "android") {
entry = fileSystem;
} else {
entry = fileSystem.root;
}
entry.getDirectory("Cordova", {
create: true,
exclusive: false
}, onGetDirectorySuccess, onGetDirectoryFail);
};
function onGetDirectorySuccess(dir) {
cdr = dir;
dir.getFile(filename, {
create: true,
exclusive: false
}, gotFileEntry, errorHandler);
};
function gotFileEntry(fileEntry) {
// URL in which the pdf is available
var documentUrl = "http://localhost:8080/testapp/test.pdf";
var uri = encodeURI(documentUrl);
fileTransfer.download(uri, cdr.nativeURL + "test.pdf",
function(entry) {
// Logic to open file using file opener plugin
openFile();
},
function(error) {
navigator.notification.alert(ajaxErrorMsg);
},
false
);
};
function openFile() {
cordova.plugins.fileOpener2.open(
cdr.nativeURL + "test.pdf",
"application/pdf", //mimetype
{
error: function(e) {
navigator.notification.alert("Error Opening the File.Unsupported document format.");
},
success: function() {
// success callback handler
}
}
);
};
I'm trying to get recapatcha v2 working in my ASP MVC project. The client's computers have IE10/IE11 and shows all intranet pages in compatibility view which causes the recaptcha not to show as it is intended.
The problem is it rarely accepts my answer even though it's right. It just shows a new image, but every once in awhile I get it right. Anyone else experience this?
If you enable compability view for google.com in IE and visit the demo site you can try it out.
reCAPTCHA requires that compatibility view is not enabled in order to work, see:
https://support.google.com/recaptcha/?hl=en-GB#6223838
You are seeing reCaptcha's fallback. It seems that you have to get two correct answers in a row. It then gives you a response code that you copy and paste into a <textarea> element.
So what you are possibly experiencing is that you aren't getting two consecutive reCaptchas correct.
You can test the fallback recaptcha by adding the fallback=true parameter to the JavaScript resource:
<script src="https://www.google.com/recaptcha/api.js?fallback=true" async defer></script>
As explained by #Coulton recaptcha does not support IE compatibility mode.
reCaptcha uses a function in javascript named querySelectorAll, and querySelector. IE 11 in compatibility mode renders as IE 7.0, and IE 7.0 and below don't seem to have the functions querySelectorAll and querySelector and that is why it fails.
Now, I am using .net webforms so you may have to adapt it a little for MVC, but here it is:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="reCaptcha.aspx.cs" Inherits="reCaptcha" %>
<!DOCTYPE html>
<script type="text/javascript">
// this defines these functions if they don't exist.
if (!document.querySelectorAll) {
document.querySelectorAll = function (selectors) {
var style = document.createElement('style'), elements = [], element;
document.documentElement.firstChild.appendChild(style);
document._qsa = [];
style.styleSheet.cssText = selectors +
'{x-qsa:expression(document._qsa && document._qsa.push(this))}';
window.scrollBy(0, 0);
style.parentNode.removeChild(style);
while (document._qsa.length) {
element = document._qsa.shift();
element.style.removeAttribute('x-qsa');
elements.push(element);
}
document._qsa = null;
return elements;
};
}
if (!document.querySelector) {
document.querySelector = function (selectors) {
var elements = document.querySelectorAll(selectors);
return (elements.length) ? elements[0] : null;
};
}
</script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js' type="text/javascript"></script>
<script src='https://www.google.com/recaptcha/api.js' type="text/javascript"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/1.3.2/jquery.min.js' type="text/javascript"></script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>reCaptcha Test</title>
</head>
<body>
<h1>reCaptcha Test</h1>
<form id="frmResult" runat="server">
<div class="g-recaptcha" data-sitekey=""></div>
<script type="text/javascript">
function IeVersion() {
//Set defaults
var value = {
IsIE: false,
TrueVersion: 0,
ActingVersion: 0,
CompatibilityMode: false
};
//Try to find the Trident version number
var trident = navigator.userAgent.match(/Trident\/(\d+)/);
if (trident) {
value.IsIE = true;
//Convert from the Trident version number to the IE version number
value.TrueVersion = parseInt(trident[1], 10) + 4;
}
//Try to find the MSIE number
var msie = navigator.userAgent.match(/MSIE (\d+)/);
if (msie) {
value.IsIE = true;
//Find the IE version number from the user agent string
value.ActingVersion = parseInt(msie[1]);
} else {
//Must be IE 11 in "edge" mode
value.ActingVersion = value.TrueVersion;
}
//If we have both a Trident and MSIE version number, see if they're different
if (value.IsIE && value.TrueVersion > 0 && value.ActingVersion > 0) {
//In compatibility mode if the trident number doesn't match up with the MSIE number
value.CompatibilityMode = value.TrueVersion != value.ActingVersion;
}
return value;
}
var ie = IeVersion();
var reCaptchaApi = "";
$(document).ready(function () {
$('.g-recaptcha').each(function (index, obj) {
grecaptcha.render(obj, { 'sitekey': reCaptchaApi });
});
if (ie.CompatibilityMode) {
// loading it twice makes it load in compatibility mode.
$('.g-recaptcha').each(function (index, obj) {
grecaptcha.render(obj, { 'sitekey': reCaptchaApi });
});
}
});
</script>
</form>
</body>
</html>
This allows reCaptcha V-2 to load in compatibility mode.