Serve up images from network to View in ASP.NET MVC - asp.net-mvc-4

I'm trying to load images from my server and then load them to a view:
var files = _directoryInfo.GetFiles()
.Where(x => x.Name.Contains(request.WarrantyReference))
.ToList();
model.Photos = files;
return View(model);
Then in the View im doing:
#if (Model.Photos.Count > 0)
{
#Html.Partial("_Photos", Model.Photos)
}
_Photos:
#model List<FileInfo>
<div class="ui items">
#foreach (var photo in Model)
{
<div class="item">
<div class="image">
<img src="#photo.FullName">
</div>
</div>
}
</div>
But nothing appears, I get the following error in the console:
Not allowed to load local resource:
file://my-server/dataphoto/WX0001 1.jpg
So I was wondering if it is possible to store the photos temporarily on my server to serve them to the View or is there another way around this?

Store the file names (or some identifier) in your Model.
Model
class Model
{
IList<string> Photos { get; set; }
Create an HtmlHelper to display your photo image.
In your example you could store "WX0001 1.jpg" as the photo identifier then when you read the file from the network server you look in a specific directory.
View
#model List<FileInfo>
<div class="ui items">
#foreach (var photo in Model)
{
<div class="item">
<div class="image">
#Html.PhotoImage(photo)
</div>
</div>
}
</div>
public static MvcHtmlString PhotoImage(this HtmlHelper html, string id)
{
var img = new TagBuilder("img");
var your_image_byte_array = read_image_from_server_using_id;
var base64 = Convert.ToBase64String(your_image_byte_array);
img.Attributes.Add("src", String.Format("data:image/gif;base64,{0}", base64));
return MvcHtmlString.Create(img.ToString());
}
Alternatively, have a look at using an Action method to display the image... Convert Byte Array to Image and Display in Razor View

you would need to copy the files somewhere where the ASP.NET user being used for the AppPool serving/hosting the website has access to. Alternatively, give the share the app pool account privileges to read. One other way would be to read the files and store them in a byte[] and finally render it on the screen/view without actually writing the files to disk.

Related

How to change text from in HTML Label from backend

I'm starting to learn ASP.NET Core MVC and just found out that the toolbox is inaccessible/disabled/grayed out, so in html I cannot use <asp:Label/> tag and have to use <label></label> tag instead.
Now I am having trouble changing the string on the HTML Tag <label></label> from the backend.
For this case I already wrote runat="server" inside the tag but still an error occured that says:
The name 'lblkpj' does not exist in the current context
Here is the example html:
<label class="text-center mb-1 fw-bold" runat="server" id="lblkpj"> </label>
and C#:
if (tbl.Rows.Count > 0)
{
lblkpj.text = "Success";
}
else
{
lblkpj.text = "Failed";
}
Where am I going wrong?
Work with Razor markup.
You can implement the logic in View by declaring the variable. And use # symbol. Razor will evaluate the expression and render the output into HTML.
And make sure that you need to return the ViewModel as a List of your model objects from the Controller to View.
View
#model List<YourModel>
#{
string status = Model.Rows.Count > 0 ? "Success" : "Failed";
}
<label class="text-center mb-1 fw-bold" id="lblkpj">#status</label>
Controller
public class YourController : Controller
{
public IActionResult YourView()
{
// Mock data
List<YourModel> list = new List<YourModel>();
return View(list);
}
}

Not able to read string value from cshtml.cs page in .cshtml page in ASP.NET Core 6.0

I am new to ASP.NET Core 6.0 and I am facing an issue while reading a value from .cshtml.cs file in .cshtml page.
I have tried to use the [BindProperty] attribute and also tried to bind value in ViewData.
Basically, I have created an HTML Table and bound it to a string value. Please find below the sample code that I tried.
cshtml.cs code:
[BindProperty]
public string HTMLRep { get; set; }
HTMLRep = reportHTML; //reportHTML has the HTML Table in the post ActionMethod
I also tried
ViewData["HTML"] = reportHTML
.cshtml markup:
#{
var val = ViewData["HTML"];
}
<panel>
#Model.HTMLRep
//Also tried -
#val
<panel>
Any help on this will be very useful. Thank you
By default, if you try to use HTML text for output it encodes it. So you have to write like following:
<panel>
#Html.Raw(Model.HTMLRep)
<panel>
This should fix your issue.
If I would you then might be solve this issue in following manner.
Web Site Dynamic Content From Backend:
[HttpGet]
public IActionResult BindDynamicContentToHtmlCard()
{
var convertedHtmlBodyList = new List<string>();
for (int i = 1; i < 10; i++)
{
StringBuilder sb = new StringBuilder();
var convertedHtmlBody = "";
sb.Append("<!DOCTYPE html>");
sb.Append("<html>");
sb.Append("<head>");
sb.Append("</head>");
sb.Append("<body>");
sb.Append("<h5 class='card - title' style='border: solid'><strong>TEST WEB SITE "+ i + " </strong></h5>");
sb.Append("<p>Simplest solution of the dynamic card generation.</p>");
sb.Append("<p>This is how you can generate dynamic Card</p>");
sb.Append("<p><strong style='color: red'>Note:</strong> For more details please check details: <a href='https://stackoverflow.com/questions/71167733/i-want-to-use-html-rawstring-where-string-contains-a-complete-html-webpage'>Details</a></p>");
sb.Append("</body>");
sb.Append("</html>");
convertedHtmlBody = sb.ToString();
convertedHtmlBodyList.Add(convertedHtmlBody);
}
ViewBag.bindToHtmlInView = convertedHtmlBodyList;
return View(); ;
}
Panel HTML:
#{
ViewData["Title"] = "BindDynamicToHtml";
}
<div class="row">
<div class="col-md-12">
#foreach (var item in ViewBag.bindToHtmlInView)
{
<panel>
#Html.Raw(item)
</panel>
}
</div>
</div>
Panel Output:
Here you can get the panel element.

return new FileStreamResult write Stream content to View instead downloading as file

Using ASP.NET Core 3.1 I am trying a simple code to generate a Stream file download OnPost
public IActionResult OnPostDwonloadFile()
{
var stream = new MemoryStream(Encoding.ASCII.GetBytes("Hello World"));
return new FileStreamResult(stream, new MediaTypeHeaderValue("text/plain"))
{
FileDownloadName = "test.txt"
};
}
The Razor Page View code:
<form method="post"
asp-page-handler="DwonloadFile"
data-ajax="true"
data-ajax-method="POST"
data-ajax-begin="AjaxOnBegin"
data-ajax-complete="AjaxOnComplete"
data-ajax-failure="failed"
data-ajax-update="#div_BusyIndicator">
<div id="div_BusyIndicator"></div>
<button type="submit" style="width: 200pt;" class="btn btn-outline-primary mr-3">test</button>
Problem is that return new FileStreamResult returns content that is displayed on the Page/View instead of downloading as text.txt.
How to solve this please?

Sitecore MVC Controller and Forms - ActionResult not rendering Layout on postback

Sitecore 7.1v1, most recent Glass Mapper, MVC4. When we submit the form POST, we get no layout with the return View. I'd prefer not to have to redirect to another page since this is supposed to be a wizard-like experience. This is also lightweight enough not to require Ajax, although we could use it as a last resort. I can't find who to make sure that while returning the View that we get the layout as well. I'm new to Sitecore MVC and pretty new at MVC in general. The PageBase that's referenced is a Custom Model using Glass.
We have the following Controller Rendering:
public class RegistrationController : Controller
{
[HttpGet]
public ActionResult VerifyAccount()
{
return View("~/Views/Public/Wizards/Registration/VerifyAccount.cshtml",
new SitecoreContext().GetCurrentItem<PageBase>());
}
[HttpPost]
public ActionResult CreateProfile()
{
ViewBag.Name = Request["VerificationType"];
ViewBag.Step = 2;
return View("~/Views/Public/Wizards/Registration/CreateProfile.cshtml",
new SitecoreContext().GetCurrentItem<PageBase>());
}
}
The default action for this is VerifyAccount(). This renders as expected. The initial view is as follows:
#inherits Glass.Mapper.Sc.Web.Mvc.GlassView<Public.Model.GlassModel.Primary.PageBase>
<div>
<h3>#Editable(a => a.Title)</h3>
<p>
#Editable(a => a.Description)
</p>
<hr />
#using (Html.BeginRouteForm(Sitecore.Mvc.Configuration.MvcSettings.SitecoreRouteName, FormMethod.Post))
{
#Html.Sitecore().FormHandler("Registration", "CreateProfile")
#Html.ValidationSummary(true, "Verification Not Selected.")
<fieldset>
#Sitecore.Globalization.Translate.Text("$Registration.VerificationTitle")
#{ var validations = new SitecoreContext().GetItem<GlassFrameBase>(Guid.Parse("{3694FC43-3DB7-470A-A1E9-2649856AAF10}"));}
<select id="VerType" name="VerificationType">
#foreach (var validation in validations.GetChildren<VerificationMethod>())
{
<option value="#validation.MethodValue">#validation.MethodName</option>
}
</select>
<input type="submit" value="Next" />
</fieldset>
}
This posts back to the CreateProfile() Method. This part works great. The only issue is that when it returns the view this time, it returns just the view without the layout.
The final view is as follows:
#using (Html.BeginRouteForm(Sitecore.Mvc.Configuration.MvcSettings.SitecoreRouteName, FormMethod.Post))
{
#Html.Sitecore().FormHandler()
<p>
<b>Verification Type Was: </b>#ViewBag.Name
</p>
<p>#ViewBag.Step</p>
<input type="hidden" value="ThisIsATest" name="TestHidden" id="TestHidden"/>
<input type="submit" name="back" value="Back" /><br />
<input type="submit" name="next" value="Next" />
}
Everything else is working exactly as expected but I'm missing something important that loads the Layout on the return trip.
I have noticed this before as well and I think it relates to this line:
#Html.Sitecore().FormHandler("Registration", "CreateProfile")
It seems to bypass the standard rendering pipeline and just call the target action. I have written a blog post on how you can control calls to different action on multiple controllers. this might help:
http://www.experimentsincode.com/?p=425
Try changing the return type of CreateProfile from ActionResult to PartialViewResult, and then return View("... to return PartialView("...
Also, here's a post about what you can return for Sitecore Controller Renderings.
http://mhwelander.net/2014/04/09/sitecore-controller-rendering-action-results-what-can-i-return/
I haven't looked deeply into form posting with Controller Renderings, but if the above suggestion doesn't work then maybe consider the execution lifestyle used in Sitecore MVC (mentioned in the post).

Passing Model Through POST

I'm having some problems with one specific part of my ASP.NET site. This page is essentially where a user edits an invoice and then posts the changes.
At this point I'm doing a re-write of an existing page, which works. I cannot figure out what the difference is other than the other one is older MVC 3.
When I first go to the EditInvoice Action:
public ActionResult EditInvoice()
{
SalesDocument invoice = null;
try
{
invoice = SomeService.GetTheInvoice();
}
catch (Exception ex)
{
return HandleControllerException(ex);
}
return View("InvoiceEdit", invoice.LineItems);
}
The model of the "InvoiceEdit" view is the List
Now the view loads fine, and displays all the document line items in a form:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<MyApp.SalesDocumentLineItem>>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Line Items</legend>
<div id="lineItems" class="table">
<div class="row">
<div class="colHButton">X</div>
<div class="colH">Item</div>
<div class="colHPrice">Price</div>
<div class="colHQty">Qty</div>
</div>
<% foreach (var item in Model.Where(m => m.LineItemType.Id == NexTow.Client.Framework.UnitsService.LineItemTypes.SaleItem || m.LineItemType.Id == NexTow.Client.Framework.UnitsService.LineItemTypes.NonSaleItem))
{ %>
<div class="row">
<%=Html.Hidden("Model.LineItemNameId", item.LineItemNameId)%>
<div class="cellButton"><button onclick="DeleteContainer(event);">X</button></div>
<div class="cell"><span class="formData"><%=item.LineItemDescription %></span></div>
<div class="cellPrice">
<span class="formData">$</span>
<%= Html.TextBox("Model.Price", item.Price, new { style="width:75px;" })%>
</div>
<div class="cellQty">
<%= Html.TextBox("Model.Quantity", item.Quantity, new { style = "width:60px;" })%>
</div>
</div>
<%} %>
</div>
</fieldset>
<p>
<input type="submit" value="Update Invoice" onclick="SequenceFormElementsNames('salesItems');" />
</p>
<% } %>
</asp:Content>
This then provides the user the ability to edit the entries, and then the user clicks the "Update Invoice" submit button. This posts to the same view and action using a POST:
[HttpPost]
public ActionResult EditInvoice(List<SalesDocumentLineItem> salesItems)
{
if (salesItems == null || salesItems.Count == 0)
{
return View("ClientError", new ErrorModel() { Description = "Line items required." });
}
SalesDocument invoice = null;
try
{
invoice = SomeService.UpdateInvoice();
}
catch (Exception ex)
{
return HandleControllerException(ex);
}
InvoiceModel model = new InvoiceModel();
model.Document = invoice;
return View("InvoicePreview", model);
}
However, eventhough this worked in the old application. In the new one, this does not work. When we breakpoint at the final EditInvoice POST action method, the collection of salesItems is NULL. What is happening!?
When you use Html.TextBox(string, object), the first argument is used as the name of the form field. When you post this form back to the server, MVC looks at your action method's argument list and uses the names of the form fields to try and build those arguments. In your case, it tries to build a List<SalesDocumentLineItem>.
It looks like you're using "Model.Something" as the names of your form fields. This probably worked in the past, but I'm guessing something changed in MVC4 such that the framework doesn't know what you're talking about anymore. Fortunately, there's a better way.
Instead of setting the name of the form field using a string, use the strongly-typed HTML helpers like this:
<% for (var i = 0; i < Model.Count; i++) { %>
<div class="row">
<%= Html.HiddenFor(model => model[i].LineItemNameId) %>
<!-- etc... -->
</div>
<% } %>
These versions of the HTML helpers use a lambda expression to point to a property in your model and say "See that property? That one right there? Generate an appropriate form field name for it." (Bonus: Since the expression is pointing at the property anyway, you don't have to specify a value anymore -- MVC will just use the value of the property the expression represents)
Since lambda expressions are C# code, you will get a compile-time error if you make a typo, and tools like Visual Studio's "Rename" feature will work if you ever change the property's name.
(This answer goes into more detail on exactly how this works.)