I want do build some pictures albuns that the user can click on it and go to a image gallery with pictures of that album.
Each algum have a thumbnail picture, a title and a link for the pictures.
In my code, I can get all the data from database. But it doesn't appear on the website.
I know I'm doing something wrong. But don't know what...
So, here's my code:
In my model, I have this code:
public List<Entities.Portfolio> GetAlbuns()
{
List<Entities.Portfolio> port = new List<Entities.Portfolio>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("usp_get_all_albuns", connection);
command.CommandType = CommandType.StoredProcedure;
SqlDataReader reader = null;
connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
port.Add(new Entities.Portfolio()
{
Imagem = (byte[])reader.GetValue(0),
Link = reader.GetString(1),
Title = reader.GetString(2)
});
}
}
return port;
}
In my controller, I'll call the method:
PortfolioController pcontroller = new PortfolioController();
protected List<Entities.Portfolio> GetAlbuns()
{
return pcontroller.GetAlbuns();
}
And in my ASP.NET page, I have this:
<div class="freshdesignweb" id="Albuns" runat="server">
<% foreach(var items in GetAlbuns())
{ %>
<!-- start article 1 -->
<article class="border c-two" style="background-image:url('<% items.Imagem.ToArray(); %>"')">
<div style="opacity: 0;" class="fdw-background">
<h4><% Eval(items.Title.ToString()); %></h4>
<p class="fdw-port">
Abrir Álbum <span class="vg-icon">→</span>
</p>
</div>
</article>
<!-- end article 1 -->
<%} %>
I can get all the data well, I tested in debug mode. But it doesn't appear in the page.
I know I'm doing something wrong, can you help me to understand how to fix this?
In my investigation I read about
Thank you.
You are missing the # sign in front of Eval:
"<%# Eval(items.Link.ToString()) %>"
Related
I've got a page in my application that will allow users to run stored procedures against the database so that they can manage their data or make changes without using SSMS. Using the SqlCommandBuilder.DeriveParameters method, I was able to successfully fetch and display all stored procedures in a select tag as well as display their input & output parameters.
Here is the contract class:
public class DatabaseUpdateModel
{
public int ClientId { get; set; }
public string StoredProcedureName { get; set; }
public List<SelectListItem> StoredProcedureNames { get; set; }
public Dictionary<string, SqlParamCollection> StoredProcedures { get; set; }
public Dictionary<int, string> ParameterInputs { get; set; }
public DatabaseUpdateModel()
{
StoredProcedureNames = new List<SelectListItem>();
StoredProcedures = new Dictionary<string, SqlParamCollection>();
ParameterInputs = new Dictionary<int, string>();
}
}
I do this in two steps - step 1 happens on the controller's index loading to fetch the stored procedure names:
Service methods:
private DatabaseUpdateModel GetDatabaseUpdateStoredProcedureNames(string connectionString)
{
_logger.LogTrace("Begin GetDatabaseUpdateModel service method");
SqlConnection connection = new SqlConnection(connectionString);
DBConnectionSetter.SetDBConnection(_SqlHelper, connectionString);
DatabaseUpdateModel model = new DatabaseUpdateModel();
IDataReader reader = _SqlHelper.GetDataReader("SELECT name FROM sys.objects WHERE type = 'p' ORDER BY name ASC", CommandType.Text, _appSettings.CommandTimeoutInSeconds, out connection, null);
while (reader.Read())
{
SelectListItem storedProcedure = new SelectListItem
{
Value = ((string)reader["name"]).Trim(' '),
Text = (string)reader["name"]
};
model.StoredProcedureNames.Add(storedProcedure);
}
reader.Close();
return model;
}
Step 2 happens via Ajax when a stored procedure is selected
public DatabaseUpdateModel GetDatabaseUpdateProcedureParameters(string connectionString, string storedProcedureName)
{
_logger.LogTrace("Begin GetDatabaseUpdateProcedureParameters service method");
SqlConnection connection = new SqlConnection(connectionString);
DBConnectionSetter.SetDBConnection(_SqlHelper, connectionString);
DatabaseUpdateModel model = GetDatabaseUpdateStoredProcedureNames(connectionString);
connection.Open();
Contract.Shared.SqlParamCollection collection = new Contract.Shared.SqlParamCollection();
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = storedProcedureName;
command.CommandType = CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(command);
foreach (SqlParameter param in command.Parameters)
{
if (param.Direction == ParameterDirection.Input)
{
collection.InputParameters.Add($"{param.ParameterName} - {param.SqlDbType}");
collection.SqlParameters.Add(param);
}
else
{
collection.OutputParameters.Add($"{param.ParameterName} - {param.SqlDbType}");
}
}
model.StoredProcedures.Add(storedProcedureName, collection);
connection.Close();
return model;
}
What this leaves me with is this:
Now I've been following various articles and resources to get to this point but now I'm having issues correctly binding these inputs to a model to be submitted either by an action or via ajax. Here's my current code in the view (the commented out line is one of my latest attempts to get this working).
#model DatabaseUpdateModel
<form>
<table id="summaryTable" class="table">
<thead>
<tr>
<td>Input Parameters</td>
<td>Output Parameters</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<ul>
#if (!string.IsNullOrEmpty(Model.StoredProcedureName))
{
for (int i = 0; i < Model.StoredProcedures[Model.StoredProcedureName].InputParameters.Count(); i++)
{
<li>
#Model.StoredProcedures[Model.StoredProcedureName].InputParameters[i].ToString()<br />
#*<input id="databaseUpdateParam[#i]" name="parameter[#i]" asp-for="#Model.ParameterInputs[#i]" type="text" />*#
<input id="databaseUpdateParam[#i]"type="text" />
</li>
}
}
</ul>
</td>
<td>
<ul>
#if (!string.IsNullOrEmpty(Model.StoredProcedureName))
{
foreach (var param in Model.StoredProcedures[Model.StoredProcedureName].OutputParameters)
{
<li>
#param
</li>
}
}
</ul>
</td>
</tr>
</tbody>
</table>
</form>
#if (Model.StoredProcedures[Model.StoredProcedureName].InputParameters.Count() > 0)
{
<button type="submit" asp-action="Foo">Submit</button>
}
Ajax function that runs when a value is selected:
function selectDatabaseUpdateStoredProcedure(clientId, storedProcedureName) {
var selected = $("#clientStoredProcedurePicker option:selected").val();
console.log(selected); // Selected Stored Procedure Name
$.ajax({
url: "/Process/GetDatabaseUpdateProcedureParameters?ClientId=" + clientId + "&StoredProcedureName=" + storedProcedureName,
success: function (data) {
console.log(data);
$("#summaryTableDiv").html(data);
}
});
}
My assumption, and everything that I read up to this point has said that I should be able to simply be able to use the name attribute to denote the dictionary's key and the value in the tag would correspond to the value entered upon form submission. However all of my attempts to achieve this are met with errors (for example that the index is not present in the dictionary).
How can this be done either through a controller action or ajax?
I wanted to have this question up so that if someone more knowledgeable happened upon it, I could maybe gain some insight to save myself even more hours of scratching my head. After reading through an article linked in this question I found that I was missing a key piece in how the HTML is rendered and came up with something like this that now correctly posts the values in the inputs. I still need to process and handle the other missing pieces from the model but at least this gets me what I need to move forward.
Here is the relevant code that allows this to work. Creating a hidden input to store the ID on its own and allowing the user to enter a string value seems to work exactly as I expect and want it to.
<td>
<ul>
#if (!string.IsNullOrEmpty(Model.StoredProcedureName))
{
for (int i = 0; i < Model.StoredProcedures[Model.StoredProcedureName].InputParameters.Count(); i++)
{
<li>
#Model.StoredProcedures[Model.StoredProcedureName].InputParameters[i].ToString()<br />
<input hidden id="databaseUpdateParamKey[#i]" name="ParameterInputs[#i].Key" value="#i" />
<input id="databaseUpdateParamValue[#i]" name="ParameterInputs[#i].Value" type="text" />
</li>
}
}
</ul>
</td>
This is within Sitefinity if that matters, and I am really new at ASP.NET and C#.
I have an image-based navigation element at the bottom of a page that links to different articles using the same template. There are 5 articles, and I would like the link to the active page/article to be hidden so there is a grid of 4 image links.
Here's a screenshot:
https://i.imgur.com/PG2Sfpo.png
Here is the code behind it:
#{
string navTitle = string.Empty;
string url = string.Empty;
if (Model.CurrentSiteMapNode != null && Model.CurrentSiteMapNode.ParentNode != null)
{
if (Model.CurrentSiteMapNode.Title == "Home")
{
navTitle = Model.CurrentSiteMapNode.ParentNode.Title;
}
else
{
navTitle = Model.CurrentSiteMapNode.Title;
}
url = Model.CurrentSiteMapNode.ParentNode.Url;
}
}
<div class="foundation-stories-container">
#foreach (var node in Model.Nodes)
{
#RenderRootLevelNode(node);
}
</div>
#*Here is specified the rendering for the root level*#
#helper RenderRootLevelNode(NodeViewModel node)
{
string[] thisPage = (node.Url).Split('/');
string thisImage = thisPage[4] + ".jpg";
<a href="#node.Url" target="#node.LinkTarget">
<div class="foundation-story-block">
<div class="hovereffect">
<img src="[OUR WEBSITE URL]/stories/#thisImage" class="img-fluid">
<div class="overlay">
<h2>#node.Title</h2>
</div>
</div>
</div>
</a>
}
So we're already getting the page URL and image file name
string[] thisPage = (node.Url).Split('/');
string thisImage = thisPage[4] + ".jpg";
Is this as easy as doing the following?
if (thisImage = thisPage)
{
foundation-story-block.AddClassToHtmlControl("hide")
}
Seems easy enough, but I don't know where to start.
I'm better at Javascript, so I do have a JS solution in place for this already, but I'd really like to find a cleaner way to do it.
<script type="text/javascript">
$(document).ready(function() {
var active = window.location.pathname.split("/").pop()
var name = active;
name = name.replace(/-/g, ' ');
jQuery.expr[":"].Contains = jQuery.expr.createPseudo(function(arg) {
return function( elem ) {
return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >=
0;
};
});
$("h2:Contains('" + name + "')").closest(".foundation-story-block").addClass("hide");
});
</script>
This exists on the main template page.
Gets the last part of the URL
Sets that as a variable called "name"
Changes the dash to a space if there is one (most of the pages are associated with names so it's like /first-last)
Then it goes and looks at the which is where the title of the page lives, and if it equals the "name" variable, the ".hide" class is added to the block.
Thanks for any help anyone can provide.
You could bind a click event to your elements with the foundation-story-block class. The reason I use .on instead of .click is because when using UpdatePanels the click event won't fire after an UpdatePanel has it's update event triggered - you might encounter a similar problem with your dynamic binding so I used .on to avoid this.
$(".foundation-story-block").on("click", function() {
// Remove the "hide" class from any elements that have it applied
$.each($(".foundation-story-block.hide"), function(index, value) {
// Remove the class using the "this" context from the anonymous function
$(this).removeClass("hide");
});
// Add the "hide" class to the element that was clicked
$(this).addClass("hide");
});
I haven't run this though an IDE so it might not be 100% correct but it will put you on the correct path.
It is possible, yes. Here is how:
...
#{
var hiddenClass = thisImage == thisPage ? "hide" : string.Empty;
}
<div class="foundation-story-block #hiddenClass">
<div class="hovereffect">
<img src="[OUR WEBSITE URL]/stories/#thisImage" class="img-fluid">
<div class="overlay">
<h2>#node.Title</h2>
</div>
</div>
</div>
I didn't understand how does server-side pagination works with MySql and Datatable in a C# MVC.
I created a Controlled in C#, in which I established the connection with a MySql database (I followed this example in order to do that):
public ActionResult connectDB()
{
const string DB_CONN_STR = "Server=MyServer;Port=MyPort;Uid=MyUid;Database=MyDB;";
MySqlConnection cn = new MySqlConnection(DB_CONN_STR);
try
{
string sqlCmd = "select * from t_documento";
MySqlDataAdapter adr = new MySqlDataAdapter(sqlCmd, cn);
adr.SelectCommand.CommandType = CommandType.Text;
DataTable dt = new DataTable();
adr.Fill(dt); //opens and closes the DB connection automatically !! (fetches from pool)
return Content(JsonConvert.SerializeObject(dt).ToString());
}
catch (Exception ex)
{
Console.WriteLine("{oops - {0}", ex.Message);
return Content(ex.ToString());
}
finally
{
cn.Dispose(); // return connection to pool
}
}
However, in this way, I retrieve all the records stored in that table, but I want to fill the Datatable (the inizialization of my datatable is located in a cshtml page) by implementing the pagination.
I read a lot of articles but I didn't found a clear example with a MySql DB.
Can someone help me, please?
Thank you!
Try this Example of server side pagination.
/Controllers/ProductController.cs
public class ProductController : Controller
{
public object Index(int? page)
{
var products = MyProductDataSource.FindAllProducts(); //returns IQueryable<Product> representing an unknown number of products. a thousand maybe?
var pageNumber = page ?? 1; // if no page was specified in the querystring, default to the first page (1)
var onePageOfProducts = products.ToPagedList(pageNumber, 25); // will only contain 25 products max because of the pageSize
ViewBag.OnePageOfProducts = onePageOfProducts;
return View();
}
}
/Views/Products/Index.cshtml
#{
ViewBag.Title = "Product Listing"
}
#using PagedList.Mvc; //import this so we get our HTML Helper
#using PagedList; //import this so we can cast our list to IPagedList (only necessary because ViewBag is dynamic)
<!-- import the included stylesheet for some (very basic) default styling -->
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />
<!-- loop through each of your products and display it however you want. we're just printing the name here -->
<h2>List of Products</h2>
<ul>
#foreach(var product in ViewBag.OnePageOfProducts){
<li>#product.Name</li>
}
</ul>
<!-- output a paging control that lets the user navigation to the previous page, next page, etc -->
#Html.PagedListPager( (IPagedList)ViewBag.OnePageOfProducts, page => Url.Action("Index", new { page }) )
my link is like
http://localhost/default.aspx?phone=9057897874&order=124556
Here Is my basic Page for passing Parameter In URL from ASP.net
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication2._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form method="get" action="default.aspx">
<label>Phone No</label>
<input type="text" name="phone" />
<br />
<label>Order No</label>
<input type="text" name="order" />
<br />
<input type="submit" value="submit" />
<br />
</form>
my c# file where I can store the prameters in Variables
namespace WebApplication2
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string strQuery;
string phone = Request.QueryString["phone"];
if (phone != null)
{
Response.Write("phone no is ");
Response.Write(phone);
}
else
{
Response.Write("You phone number is not correct");
}
string order_no = Request.QueryString["order"];
if (order_no != null)
{
Response.Write("Order No is ");
Response.Write(order_no);
}
else
{
Response.Write("You Order number is not correct");
}
//How I can Connect to Mysql Server
strQuery = "SELECT order_status where orde01=''" + order_no + "'' and phone01=''" + phone + "''";
Response.Write(strQuery);
}
}
I'm trying to doing something like this but it's only give me whole query as string.
I am new on this topic.
Any help will be appreciate
Thanks
First off, concatenating a sql statement based on input that the user can change, especially when stored as a string is how SQL Injection Vulnerabilities are created. Don't be that guy.
as for tokenalizing your query string, use named parameters. assume this is your query string
?orderid=777&phone=777-777-7777
Response.QueryString["orderid"]
would return '777' and
Response.QueryString["phone"]
woudl return '777-777-7777'
as for your sql injection issue, you have a couple options. one is a parameterized sql statement, see the C# example here: http://rosettacode.org/wiki/Parametrized_SQL_statement
or use a stored procedure with parameters. the least desirable but minimally acceptable option is to regex validate your input parameters strictly, especially killing characters like '=;% -- and a few others.
EDIT: now that I've had some time to work up a sample, check this out. This sample needs to be customized to your database, but its working on my mysql DB with a test table. you will need to install the MySQLConnector pack and add a project reference to 'MySql.Data' before the code will compile correctly.
namespace WebApplication2
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) {
//define some regex patterns for validating our data.
const string PHONEREGEX = #"((\(\d{3}\))|(\d{3}-))\d{3}-\d{4}";
const string ORDERNUMREGEX = #"\d*";
bool isValid = true;
string phone = Request.QueryString["phone"]; //read phone from querystring.
//validate that arg was provided, and matches our regular expression. this means it contains only numbers and single hyphens
if(!string.IsNullOrWhiteSpace(phone) && System.Text.RegularExpressions.Regex.IsMatch(phone, PHONEREGEX)){
Response.Write(HttpUtility.HtmlEncode(string.Format("The phone number is {0}", phone))); //HTML Encode the value before output, to prevent any toxic markup.
} else {
Response.Write("Phone number not provided.");
isValid = false;
}
string orderStr = Request.QueryString["order"]; //read ordernum from querystring
long order = long.MinValue;
//validate that order was provided and matches the regex meaning it is only numbers. then it parses the value into 'long order'.
if(!string.IsNullOrWhiteSpace(orderStr) && System.Text.RegularExpressions.Regex.IsMatch(orderStr, ORDERNUMREGEX) && long.TryParse(orderStr, out order)){
Response.Write(HttpUtility.HtmlEncode(string.Format("The order number is {0}", order))); //use 'long order' instead of orderStr.
} else {
Response.Write("Order number not provided.");
isValid = false;
}
//if all arguments are valid, query the DB.
if (isValid) {
Response.Write(GetOrderStatus( phone, order));
}
}
private static string GetOrderStatus(string phone, long order) {
string status = "";
//create a connection object
string connstring = "SERVER=<YOUR MYSQL SERVER>;DATABASE=<YOUR DATABASE>;UID=<YOUR USER>;PASSWORD=<YOUR PASSWORD>-";//this is a connection string for mysql. customize it to your needs.
MySql.Data.MySqlClient.MySqlConnection conn = new MySql.Data.MySqlClient.MySqlConnection(connstring); //put your connection string in this constructor call
//create a SQL command object
using (MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand()) { //use a using clause so resources are always released when done.
cmd.Connection = conn;
cmd.CommandText = "SELECT `Order_Status` FROM `<YOUR TABLE>` WHERE `Order` = #order AND `Phone` = #phone"; //this needs a From statement
//add parameters for your command. they fill in the #order and #phone in the sql statement above. customize these to match the data types in your database.
cmd.Parameters.Add("order", MySql.Data.MySqlClient.MySqlDbType.Int64,11).Value = order; //do not use # sign in parameter name
cmd.Parameters.Add("phone", MySql.Data.MySqlClient.MySqlDbType.VarChar, 50).Value = phone;
//execute the command, read the results from the query.
cmd.Connection.Open();
using (MySql.Data.MySqlClient.MySqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
status = reader.GetString("Order_Status");
}
cmd.Connection.Close();
}
}
return status;
}
}
}
You should be using
Request.Form["phone"]
Request.Form["order"]
instead of
Request.QueryString["phone"]
Request.QueryString["order"]
The reason for this is, you are doing a postback and never redirect to a url with those values set as a querystring
However your question title would suggestion your have a url which contains something like
http://yourdomain.com?phone=0123456789&order=17
"Only images or images wrapped in links are allowed in the slider div. Any other HTML will break the slider."
What would be the best way to programatically insert images from a database in c#?
I was using a label inside the div id="slider" tag but then realized the label would create the images within a span tag and therefore break the slider.
lblSlider.Text += "<img src=\"" + URL + "\" alt=\"" + address + "\" title=\"<a href='Featured/" + address" + address + ", " + city + "</a>\" />";
Use markup like this...
<img src='ImageHandler.ashx?ProductID=<%# Eval("ProductID")%>'
alt="<%# Eval("ProductName") %>" title="<%# Eval("ProductName") %>" />
... in conjunction with an image HttpHandler class like this (adapt for your own particular DB schema):
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.Request.QueryString["productID"] != null)
{
try
{
string ProductID = context.Request.QueryString["ProductID"];
if (Convert.ToInt32(ProductID) > 0)
{
const string CONN
= "Initial Catalog=xxx;Data Source=xxx;Integrated Security=SSPI;";
string selectQuery
= "SELECT Photo FROM dbo.Products WHERE dbo.Products.ProductID="
+ ProductID.ToString();
SqlConnection conn = new SqlConnection(CONN);
SqlCommand cmd = new SqlCommand(selectQuery, conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
context.Response.BinaryWrite((Byte[])dr[0]);
dr.Close();
conn.Dispose();
// context.Response.End();
// caused an "Abort thread" error
// - this is correct and is a special exception
}
}
catch (Exception ex)
{
ErrorReporting.LogError(ex);
}
}
else
throw new ArgumentException("No ProductID parameter specified");
}
public bool IsReusable
{
get
{
return true; // multiple images otherwise false
}
}
}
Okay, I haven't tried the other solution but I did this and it works:
Here are some global c# variables:
protected int count;
protected string[] arr = new string[20];
Then I assign values to the string array from my database in the Page_Load method.
And then I just write the nivo slider with javascript on my page:
<script type="text/javascript">
document.write("<div id='slider' class='nivoSlider'>");
var count = <%= count %>;
var myArray = <% = new JavaScriptSerializer().Serialize(arr) %>;
for(var i = 0; i < count; i++) {
document.write(myArray[i]);
}
document.write("</div>");
</script>
This solution seems easier to me, but if anyone thinks I should use the other solution over this one, let me know. Oh, and don't forget the namespace System.Web.Script.Serialization
I have same requirement and tried the below code to accomplish the dynamic loading of images basing on category. These image loaded from my database. I am new to ASP.Net please let me know if I did anything wrong or did any blunders :).
in ASP.Net file:
I am using nivo slider append method
<script type="text/javascript">
$(window).load(function() {
$('#slider').append('<img id="ad5" src=<%=__ad1ImageUrl %> />');
$('#slider').append('<img id="ad6" src=<%=__ad2ImageUrl %> />');
$('#slider').append('<img id="ad7" src=<%=__ad3ImageUrl %> />');
$('#slider').append('<img id="ad8" src=<%=__ad4ImageUrl %> />');
$('#slider').nivoSlider();
});
</script>
My table looks like this:
<table style="height: 183px; width: 100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="left">
<div id="wrapper">
<div class="slider-wrapper theme-default">
<div class="ribbon">
</div>
<div id="slider" class="nivoSlider">
<!-- note that no images added here -->
</div>
</div>
</div>
</td>
</tr>
</table>
In the code behind:
Use variable to store image url(s). You can now get the URL(s) from DB and get populated. In my code i have used these variables (can use array also) to capture url path. You can get the paths from any source like Database, Xml or ...
public string __ad1ImageUrl = "";
public string __ad2ImageUrl = "";
public string __ad3ImageUrl = "";
public string __ad4ImageUrl = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
__ad1ImageUrl = "UserControls/Images/mainBanner1.jpg";
__ad2ImageUrl = "UserControls/Images/mainBanner2.jpg";
__ad3ImageUrl = "UserControls/Images/mainBanner3.jpg";
__ad4ImageUrl = "UserControls/Images/mainBanner4.jpg";
}
}