How to get YouTube URL from Database and display Video In view - c#

I need to Get youtube URL which is stored in database and display in the view. While saving into the database I am saving the complete URL like "https://www.youtube.com/watch?v=is0A9x8q_zA".
But with below code nothing display. I cannot store only ID (is0A9x8q_zA) from the above URL into the database, because I am storing different type of URL inside the same table like youtube url, blogs URL, tutorial URLs.
How do I display youtube video? Is there a better option?
My View code :
<div class="col-md-2">
#foreach (var item in group)
{
if (item.urltype == "YouTube")
{
<iframe src=#Url.Content(item.url) width="400" frameborder="0"></iframe>
}
</div>

In order to embed Youtube video, you need to provide different URL. You can use that URL from the database to get the id and apply a different format to a "src" attribute
Your view file
<div class="col-md-2">
#foreach (var item in group)
{
if (item.urltype == "YouTube")
{
//get URI first
var videoURI = new URI(item.url);
//get video id from URI
var videoId = var videoId = HttpUtility.ParseQueryString(videoUrl.Query).Get("v");
<iframe src="https://www.youtube.com/embed/#videoId" width="400" frameborder="0"></iframe>
}
</div>
I hope this helps.

Check generated HTML (Browser Dev tools : Inspect element) to make sure URL is getting loaded properly.
Also, https://developers.google.com/youtube/iframe_api_reference
has an example. Hope it helps.

Related

How to deal with input=file / IFormFile two-way binding in Razor Pages

I have an entity that has byte[] to store logos in the database as varbinary. But to use this model on a Razor Page, I have extended it and added a IFormFile property to receive the uploaded file.
public class Company
{
public string Name { get; set; }
public byte[] Logo { get; set; }
}
public class CompanyModel : Company
{
[DataType(DataType.Upload)]
[FromForm(Name = "UploadedLogo")]
public IFormFile UploadedLogo { get; set; }
}
And in a method I fetch this company from the database and set IFormFile accordingly:
var response = await _companyService.GetByIdAsync(id);
if (response != null)
{
if (response.Logo != null)
{
using (var stream = new MemoryStream(response.Logo))
{
var formFile = new FormFile(stream, 0, stream.Length, response.Name, response.Name);
formFile.Headers = new HeaderDictionary()
{
new KeyValuePair<string, StringValues>("Content-Disposition", $"form-data; name=\"Company.UploadedLogo\"; filename=\"{response.Name}.png\""),
new KeyValuePair<string, StringValues>("Content-Type", "image/png"),
};
response.UploadedLogo = formFile;
}
}
return response;
}
And the UploadedLogo is populated and I bind that on Razor Page
<form method="post"
enctype="multipart/form-data"
data-ajax="true"
data-ajax-method="post"
data-ajax-begin="begin"
data-ajax-complete="completed"
data-ajax-failure="failed">
...
<div class="form-group row">
<div class="col-sm-2 text-right">
<label asp-for="#Model.Company.Logo" class="col-form-label"></label>
</div>
<div class="col-sm-9">
<input type="file" class="dropify" data-height="200"
asp-for="#Model.Company.UploadedLogo"
data-max-file-size="100K" data-allowed-file-extensions="png jpg jpeg" />
</div>
</div>
...
<div class="form-group modal-actions">
<input type="submit" class="btn btn-primary btn-icon-text btn-md btn-save-editing" value="Save" />
</div>
</form>
By the way, I am using Dropify as file upload plugin and jquery-ajax-unobtrusive library to handle post requests. Here is the post method:
public async Task<CompanyModel> OnPostAsync(CompanyModel company)
{
CompanyModel result = new CompanyModel();
try
{
if (company.UploadedLogo != null)
company.Logo = await company.UploadedLogo.GetBytes();
var response = await _companyService.SaveAsync(company);
if (response != null)
result = response;
}
catch (Exception ex)
{
_Logger.LogException(ex);
}
return result;
}
Now here is the scenario:
When I am adding a new company, I enter company name and browse a file from my computer, and save the data. I can see Uploaded logo in company model received in post request, which is then converted to byte[] and saved in database. Everything is fine. Below is the fiddler capture:
Fiddler capture for INSERT
Problem starts when I try to edit the company. I open the company, service fetches the data, convert byte[] to IFormFile and the data (name + logo) is shown on the form. I just edit the name, do not touch the logo and let it be as it is and hit save. At this point, the Uploaded logo is null in company model received in post request. Below is the fiddler capture:
Fiddler capture for UPDATE
I can see the difference in the posted requests captures clearly. The file is not there in the case of edit. But I don't know how to fix this. It has been a day I am hurting my brain on this, can anyone assist me on this please?
UPDATE: Added fiddler captures as well.
I know this is not the best solution, but I managed to work it.
What I did is, I converted the image bytes into base64 data-uri of the image and save the uri in an input[hidden]. I also added another input[hidden] to save the flag that whether the user has changed the logo or not. And when the user changes the logo, I update these hidden fields with the new base64 data-uri of uploaded image and flag=true. And if the user does not change the image, the uri is the same and flag=false. Now on save, I get the uri string and the flag. If the flag is true, I convert the uri into the image and persist it in the database.

Build Menu Items From Controller

I am creating HTML Menus from controller. Menus are stored in database and I make html tag as below :
foreach (UIMenuModel item in list)
{
if (item.Controller != "Home")
{
string line = string.Format(#"<li><a asp-area=""{0}"" asp-controller=""{1}"" id=""{1}""
asp-action = ""{2}"" style = ""font-size:16px;;"" > {3} </a></li>", item.Area, item.Controller, item.Action, item.LinkText);
sb.Append(line);
}
}
which gives me below HTML :
<li><a asp-area="" asp-controller="CrossApproval" id="CrossApproval" asp-action="Index" style="font-size:16px;;"> Cross Approval </a></li>
Other Menu Item, Which is written in HTML itself, gives below HTML in browser.
<li><a id="CrossRequest" style="font-size:16px" href="/CrossRequest">Cross Request</a></li>
On UI, it looks perfect. However, I am not able to click and navigate to desired controller and action methods. Can someone please help me to identify while this anchor tag is not allowing me to navigate.
Use RazorLightEngine to convert plain string as rendered Razor string:
string content = "Hello #Model.Name. Welcome to #Model.Title repository";
var model = new
{
Name = "John Doe",
Title = "RazorLight"
};
var engine = new RazorLightEngine();
string result = engine.ParseString(content, model);
And then add it any place in razor view like encoded string
<div>
#Html.Raw(result)
</div>
As posted in Question, HTML with href was working fine. So, I decided to mimic the same behaviour from the controller and changed my code as below :
string line = string.Format(#"<li><a asp-area=""{0}"" id=""{1}"" href=""/{1}/{2}""
style=""font-size:16px"">{3}</a></li>", item.Area, item.Controller, item.Action, item.LinkText);
This generated a link which I can click and navigate.

Displaying image from database in webpages

I am creating a website in visual studio. I want retrieve and display image (of datatype image from sql server database) in webpage. I have a .cshtml page and got the following code to display some of the fields of the table. I am able to display everything except the image datatype column. I am using razor syntax.
MY code
#{
var db1 = Database.Open("database1");
var selectQueryString = "SELECT * FROM Recipes ORDER BY date";
}
<div class="left-content">
<h5>Recent Posts</h5>
<table>
<tbody>
#foreach(var row in db1.Query(selectQueryString))
{
<tr>
<td>#row.image</td>
<td>#row.title</td>
<td>#row.description</td>
</tr>
}
</tbody>
</table>
This is my output in the webpage:
Recent Posts
System.Byte[] testaspform ufegewu
System.Byte[] testone qfeyqo
System.Byte[] testtwo oadiufh
As you could see the first column show System.Byte[] instead of the image.
You can't render an image in an html file without using an <img/> tag.
What you can do is place an <img> tag and create a FileContentResult in your Controller and call it in the source of your tag using the #Url.Action() helper...
==Code==
In your HTML:
<img src="#Url.Action("ProcessImage", routeValues: new { imageToProcess = row.image })" />
In your Controller:
public FileContentResult ProcessImage(byte[] imageToProcess)
{
return new FileContentResult(imageToProcess, "image/jpeg");
}
...
Make sure to place the ProccessImage method in the same controller as the one that holds the ActionMethod that renders the view you are in, if that's not the case, then use:
HTML:
<img src="#Url.Action("ProcessImage", routeValues: new { controller = "{CONTROLLER_NAME}", imageToProcess = row.image })" />
I didn't build the code given above, so you might have to resolve any typo/syntax error...

Reloading Partial View with JQuery

I have a page with a video at the top and a list of videos you can choose from. Currently, clicking a link in the video list will reload the entire page. I need it to only refresh the partial view I have containing the video at the top of the page.
I saw several posts here on SO showing how to reload partial views with JQuery, but couldn't get it to work correctly in my situation. I'm unsure how to pass the correct id of the video along.
Controller:
public ActionResult Videos(int topVideo = 0)
{
VideosModel model = new VideosModel();
model.Videos = StatsVideoService.GetEntityList(new Lookup(TableStatsVideo.IsDeleted, false)).OrderByDescending(x => x.DateCreated).ToList();
if (topVideo == 0)
model.TopVideo = model.Videos.First();
else
{
model.TopVideo = model.Videos.Where(x => x.StatsVideoId == topVideo).FirstOrDefault();
if (model.TopVideo == null)
model.TopVideo = model.Videos.First();
}
return View(model);
}
View:
#model Project.Models.VideosModel
<section class="videos">
<div id="top_video">
#{Html.RenderPartial("StatsVideo", Model.TopVideo);}
</div>
<ul>
#foreach (var item in Model.Videos)
{
<li>
<div class="videoList">
<a href ="#Url.Action("Videos", "Home", new { topVideo = item.StatsVideoId })">
<img src="#Url.Content("~/Content/img/video-ph.png")" />
</a>
<p class="videoTitle">#item.Title</p>
</div>
</li>
}
</ul>
</section>
If there's any more information needed, please let me know.
After several hours of bashing my head against the wall, I got it to work! Just as a reference to anyone else in the future who's viewing this article, here's how I got it to work:
I set the onclick of the link to point to a javascript method, passing in the id of the video as a parameter:
#foreach (var item in Model.Videos)
{
<li>
<div class="videoList">
<a href ="#" onclick="updateTopVideo(#item.StatsVideoId)">
<img src="#Url.Content("~/Content/img/video-ph.png")" />
</a>
<p class="videoTitle">#item.Title</p>
</div>
</li>
}
And then I included this script in the view at the bottom:
<script>
var updateTopVideo = function (itemId) {
var url = '#Url.Content("~/Home/StatsVideo/")';
url = url + itemId;
$.get(url, "", callBack, "html");
};
var callBack = function (response) {
$('#top_video').html(response);
};
</script>
Finally, I added a method to my controller that would return the partial view needed for the video at the top of the screen:
public ActionResult StatsVideo(int Id)
{
IStatsVideo vid = StatsVideoService.GetEntity(new Lookup(TableStatsVideo.StatsVideoId, Id));
if (vid == null)
vid = StatsVideoService.GetEntityList(new Lookup(TableStatsVideo.IsDeleted, false)).OrderByDescending(x => x.DateCreated).FirstOrDefault();
return PartialView(vid);
}
This code should be fairly easy to understand. Basically, the onclick calls the first javascript method, which then calls the controller. The controller builds the partial view and returns it. The first javascript method passes it to the second javascript method which sets the html of the div "top_video" to be the returned partial view.
If anything doesn't make sense, or anyone's having trouble with this in the future, let me know and I'll do my best to offer some help.
I think there may be several confusing and inconsistent elements here.
First, you are returning a full view instead of a partial view. This reloads all containing elements, not just the part that is relevant to your partial view.
Second, you are using Url.Action, which only generates the url. I would recommend using Ajax.ActionLink, which allows you to do fully ajax calls, refreshing the content of your partial div and updating a target div element.
instead of:
<div class="videoList">
<a href ="#Url.Action("Videos", "Home", new { topVideo = item.StatsVideoId })">
<img src="#Url.Content("~/Content/img/video-ph.png")" />
</a>
<p class="videoTitle">#item.Title</p>
</div>
try the more modern solution
<div class="videoList">
#Ajax.ActionLink(
"Videos",
"Home",
"new { topVideo = item.StatsVideoId },
new AjaxOptions {
HttpMethod = "GET",
OnSuccess = "handleSuccess"
}
)
</div>
This way you can be very specific on what you want each link to do, and you can pass along multiple parameters as well as define a callback function. You can also use "UpdateTargetId" in your ajax options to load your newly refreshed partial view into a DOM element.
You can remove the around the image and just store the url generated by the Url.Action in a data-href attribute.
Then you can use the jquery load method to load the data:
$(".videolist>img").click(function () {
$("#content").load($(this).data("href"));
});
I created a fiddle that loads content dynamically here, so you can play with it if you want: http://jsfiddle.net/bTsLV/1/

set src property in view to a url outside of the MVC3 project

I am trying to create an application that will display images that are stored locally on the webserver. Here is what I have in my view, note that "entry" are absolute addresses like "C:\Images\Image1.jpg". However, when I run it, I get "Not allowed to load local resource: file:///C:/Images/ImageName.jpg" in the console log. So maybe it tries to access the image on the client. How do I tell my view to access the local webserver path and not look for the image source on the client? Please note that moving the images into project directory is not an option, because the images are stored on a different drive on the webserver.
<!-- language: c# -->
#model List<String>
<div style="height: 500px; overflow:scroll;">
<h2>
ScreenShots for testMachine</h2>
#foreach (var entry in Model)
{
<div class="nailthumb-container square-thumb">
<img alt="screenshot" src="#Url.Content(entry)" />
</div>
}
</div>
You cannot directly serve images outside of your ASP.NET MVC 3 application to the client. That would be a huge security vulnerability if the client could access arbitrary files on your server.
You will need to write a controller action that will return them and then point your src property of your <img> tags to this controller action.
public class ImagesController: Controller
{
public ActionResult SomeImage()
{
return File(#"C:\Images\foo.jpg", "image/jpeg");
}
}
and inside your view:
<img src="#Url.Action("SomeImage", "Images")" alt="" />
You could also pass the image name as parameter to the controller action:
public class ImagesController: Controller
{
public ActionResult SomeImage(string imageName)
{
var root = #"C:\Images\";
var path = Path.Combine(root, imageName);
path = Path.GetFullPath(path);
if (!path.StartsWith(root))
{
// Ensure that we are serving file only inside the root folder
// and block requests outside like "../web.config"
throw new HttpException(403, "Forbidden");
}
return File(path, "image/jpeg");
}
}
and in your view:
<img src="#Url.Action("SomeImage", "Images", new { image = "foo.jpg" })" alt="" />
The above code was useful for me, with a change like this
System.Web.UI.Page page = new System.Web.UI.Page();
string filePath = page.Server.MapPath("~/Log/" + fileName);
if (!filePath.StartsWith(filePath))
{
throw new HttpException(403, "Forbidden");
}
return File(filePath, "Content-Disposition", "attachment;filename=TableImportLog.csv");
}
the file thrown to the user is with file name like this "attachment;filename=TableImportLog.csv", but i want the file name as "TableErrorLog.csv"
need help for the same!

Categories

Resources