c# - Access elements created by jquery in c# method - c#

In a user control I have an unordered list that contains items showing editable file data.
I create these items in my javascript using a JSON string set in a hidden field when the page is loaded or when the controlling element (AJAX async file upload) performs it's OnClient_UploadComplete function.
Everything I have is solid so far: the items are created on the client side, and I can get any values changed using an existing hidden field and transfer the data back to a BL object when I need it.
My problem is that during the server-side On_UploadComplete function, my server code cannot find any of the dinamically created items created by my javascript to add essential data to the new item.
I have to be missing something. The value I get from the control is "/r/n"..
My best guess is that my c# code is set up wrong. On the page, to find the ul I have:
Control m_ulFileItems = m_fuPhotoUpload.FindControl("m_ulFileItems");
I'll do some more loking, but this is an important aspect of getting this control to work.

I do not have any idea how you could be able to access these controls on server side. However, what I would suggest is that you pass their values from client to server, perhaps like this:
$.ajax({
url: ...,
type: ...,
data: ids and values from your controls in json format
});
Here are some more details:
if this is the HTML:
<div>
<div id="placeHolder"></div>
<input type="button" value="Submit" onclick="submit();" />
</div>
And I have added some text boxes the following way:
$(document).ready(function () {
for (var idx = 0; idx < 10; idx++) {
$('<input class="myInput" type="text" />').appendTo($('#placeHolder'));
}
});
Then this should work:
function submit() {
var jsonInput = '{';
var inputList = $(".myInput");
for (var idx = 0; idx < inputList.length; idx++) {
jsonInput = jsonInput + 'txt_' + idx + ': ' + $(inputList[idx]).val() + ',';
}
jsonInput = jsonInput.substring(0, jsonInput.length - 1);
jsonInput = jsonInput + '}';
alert(jsonInput);
$.ajax({
url: "WebForm1.aspx/HandleSubmitClick",
data: jsonInput
});
}
Hope it helps.
If you do not like the Ajax call to the server I can suggest to use a hidden control, and put that string into the hidden control before you go to the server. Then you will be able to take the value of that hidden control on the server side.
Anyway, this is the basic idea - collect and prepare the data on the client side, then send it to the server side somehow.

Add a hidden field to the page and before posting back to the server, scan all the items in the list, maybe create a JSON object which contains all the needed info from the created items, and set the hidden field value to this JSON. Now you should be able to grab that value and parse the JSON in C# and handle it from there.

Related

Uploading Images with ASP.NET MVC

I'm building a craigslist clone with ASP.NET MVC + SQL Server and I'm stuck. I'm not sure how to go about uploading and storing images. Through my research it seems better to store images in the server's file system rather than on the SQL database, but it can be stored in SQL as varbinary(MAX). Is my assessment correct?
I have a dropzone where you can click and drag multiple images into it and javascript that converts them to an array of blobs. So far I have the submit button make an ajax post request with the array of blobs that I can see in the Controller through Request.Form.Files. However I also want to send over other data from the rest of the form using the ViewModel.
This is the javascript that creates the blob array and posts it with ajax:
function buildFormData() {
//Create and build formData
formData = new FormData();
images.forEach((image, index) => {
formData.append('images[]', image, 'image:' + index);
})
//Make post request
$.ajax({
url: 'Home/UploadImage',
type: 'POST',
data: formData,
processData: false,
contentType: false,
});
}
function setupReader(file) {
//console.log("File is blob? ", file instanceof Blob); -> true
images.push(file);
var name = file.name;
var reader = new FileReader();
reader.onload = function (e) {
// Create HTML element for image (simplified)
var previewImg = '<img class="preview-image" src="' + e.target.result + '" />';
//Add img preview element to boxZone
boxZone.append(previewImg);
}
reader.readAsDataURL(file);
}
function readFiles(input) {
console.log($);
for (var i = 0; i < input.files.length; i++) {
setupReader(input.files[i]);
}
console.log("Images: ", images);
}
This seems like a good start, I can see the files in Request.Form.Files using the debugger inside of Home Controller UploadImage method, but I bet there's an easier way using the ViewModel.
What's the best way to include a variable-length array of blobs in my View model? Maybe using the FormFile or FormFileCollection classes? Or should I just use ajax to post the rest of the form data along with the images like above? Any solution I haven't considered?
Secondly, once the images are on the server I'm not sure how exactly to use the file system to store them. This is a snippet of code from the .NET docs that seems to be what I'm looking for:
using (System.IO.FileStream fs = System.IO.File.Create(pathString))
{
for (byte i = 0; i < 100; i++)
{
fs.WriteByte(i);
}
}
These are the questions I'm basically asking:
Should I store Images on the file system or SQL database?
2.Should I use Ajax to make the request?
If not:
How should I use a ViewModel to send an array of blobs?
Should I use FormFile or FormFileCollection classes to represent the images in the view model? Or a custom Image class with a byte[] field to hold the image itself?
Can anyone let me know if I'm going in the right direction, and which methods I should use to upload and store these images that I haven't considered?

Generate list based on selected option

I'm trying to create a page for admins to create new users. When these users are created they will also have a role that they are assigned, and each of those roles will have a list of associated rights. The role will be selected from a dropdownlist of roles. After the role has been selected, but before the user has been created I want the list of associated roles to be displayed on the side of the form so they can see if the rights associated with that role are what they want.
I'm not entirely sure how to approach this problem without reloading the entire page after selecting a role. I'm sure how to have a refresh on a div when the information changes
You can use AJAX to achieve this.
Here is a simple solution to start with. First, create an action method in your controller which accepts the roleId value and get's the rights associated with that role and return that as JSON array.
In the below example, I am simply hard coding 2 rights. You can replace this implementation with however you want to get the data(may be from a database) using the roleId param value.
public JsonResult RoleDetails(int roleId)
{
// Hard coded data.
// Replace with data from your db using roleId value
var rightList = new List<string> { "Admin", "Editor" };
return Json(rightList);
}
So when called with a request URL like /Home/RoleDetails?roleId=2, this action method will return data like this(JSON array).
["Admin","Editor"]
Now, Render your select element with the Roles as options. We shall store the path to the action method in a data attribute on the SELECT element. For example, your rendered HTML should be like this.
<select id="selectedRole" data-url="/Home/RoleDetails">
<option>Select one</option>
<option value="1">Role A</option>
<option value="2">Role B</option>
<option value="3">Role C</option>
</select>
<div id="role-details"></div>
We also rendered a div to show the details.
I am assuming you know how to render a SELECT element. If you do not, please refer
Select Tag Helper in ASP.NET Core MVC post
You can use the Url.Action helper to generate the correct path to the RoleDetails action method, for example,
<select id="selectedRole" data-url="#Url.Action("RoleDetails","Home")">
Now you can use JavaScript to listen to the change event of the SELECT element, read the selected option value, make an ajax call to the action method we created above, get the data ,which is a JSON array, and update the UI using that.
Here is a working sample using jQuery for DOM manipulations.
$(function () {
// Listen to "change" event on SELECT
$("#selectedRole").change(function () {
//Get the value of selected option
var roleId = $(this).val();
var url = $(this).data("url") + "?roleId=" + roleId;
//Make the AJAX call
$.getJSON(url).then(function (data) {
var list = "";
// Loop through the JSON array and build HTML for a list of P tags.
$.each(data, function (index, item) {
list += "<p>" + item + "</p>";
});
// Update the Div content
$("#role-details").html(list);
}).fail(function (e) {
$("#role-details").html("Error getting data");
console.warn(e);
});
});
})

Print out values from text file to text area

so my first attempt at asking the question was idiotic - I do apologise
So I am reading the contents of a text file - which is just rows of numbers. I am trying to calculate the sum of each row and print the answer out individually in descending order.
Here is the code in my controller :
public void ReadFromText()
{
Array LogFileData = null;
var logFileNameWithPath = Server.MapPath(#"~/Docs/Q1InputFile.txt");
if (System.IO.File.Exists(logFileNameWithPath))
{
LogFileData = System.IO.File.ReadAllLines(logFileNameWithPath);
foreach (var line in LogFileData)
{
//code goes here
}
}
ViewBag.logFileContent = LogFileData;
}
I am struggling to send the content from the text file to the text area and with the for each in order to calculate the sum of each row.
Here is the code for the view :
<h2>Question1</h2>
<div class="jumbotron">
<p class="lead">Please click the button to load the results</p>
<input type="button" title="LoadAnswer" value="Click me" id ="btn_run")
onclick="location.href='#Url.Action("ReadFromText", "Question1")'" />
#if (ViewBag.logFileContent != null)
{
foreach (string dataLine in ViewBag.logFileContent)
{
#dataLine
<br />
}
}
</div>
#Html.TextArea("ReadFromText", "Question1")
<div>
#Html.ActionLink("Back to Home", "Index", "Home")
</div>
Sorry this a basic question - but I new and trying to learn from this
Please advise
Assuming that your button is html and in browser on client side and file is residing on server in your solution directory (not on client side)
I would do following
When a button in browser is pressed I will fire an ajax call to server.
On server controller would open a file stream to this file and read lines one by one or whatever way you want to do with them and get the output sent out in json format.
When server returns output to ajax response i will replace the text area with that response or append it if needed.
All these three steps can be done individually with test data. I would first create an ajax test and on controller return a number and work on js to populate it in text field. Once that is done you only need to work on file read function in controller and return what is in file or summed from file etc.
On click of button make an AJAX call
Sample Ajax code:
$.ajax({
type : 'POST',
url : '#Url.Action("your controller and actions goes here")',
dataType : 'json',
data : {
//Send file path if it is dynamic
},
success : function (data) {
//Logic to format and display your text file data
},
error : function (ex) {}
});
C# - Server side code:
string text;
var fileStream = new FileStream(#"c:\file.txt",FileMode.Open,FileAccess.Read);
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
text = streamReader.ReadToEnd();
}
send text in the JSON format to the client and display it as per your requirment
Refer this link for AJAX implementation http://dotnetmentors.com/mvc/jquery-ajax-call-with-jsonresult-in-asp-net-mvc.aspx
I prefer to read line by line from txt file and then I create a stringBuilder and send it to a textare element like this.
List<string> linesFromFile= File.ReadAllLines(filePath).ToList();
StringBuilder str = new StringBuilder();
foreach (string item in linesFromFile)
{
str.AppendLine(item);
}
ViewBag.RobotsTxt = str;

How to get html hidden field value inside c#?

I used a hidden field inside li tag in c#. please help me to get the value of hidden field in it..
public string text="";
for (var i = 0; i < dt.Rows.Count; i++)
{
text += "<li class=''>";
text += "<input type='hidden' id='hid_dtlid' name='hid_dtlid' value='" + dt.Rows[i]["Spindtlid"].ToString() + "'/>";
text += "</li>";
}
All the name attributes of the hidden field elements should be unique. This can be accessed on the server (provided they are all nested in a html form element). You simply make you use of Request.Form collection.
Say below is what your markup rendered by asp.net looks like
<form method="post" action="foo.aspx">
<!-- other stuff -->
<input type="hidden" name="fooField" value="bar"/>
<!-- more other stuff -->
</form>
Note that this is not an element marked with runat="server". And even if its so, you wouldn't know the difference unless you inspect carefully.
On the server-side you can access it as follows:
var value = Request.Form["fooField"]; //stores "bar"
In jquery it would be:
thevalue = $('#hid_dtlid').val()
If you're loking for server side on postboack Request.Form["hid_dtlid"]
Asp.net is nothing but a series of request and responsonses with some fancy absctration on top. The basics are still accessible through the Request and Response objects
Since you have not added these hidden fields as a C# hidden field object hence they will not be available directly.
However with post back these fields will be sent by the browser client in the header in Request.Form collection which can be extracted like below:
var hiddenElements = Request.Form["hid_dtlid"] ;//it will return an array of fields with name hid_dtlid
As you want to get the cotnrol value directly in c# you need to set runat="server" for that control asp.net web forms.
<input runat="server" type='hidden' id='hid_dtlid' name='hid_dtlid' value='" + dt.Rows[i]["Spindtlid"].ToString() + "' />
when it will post data you can get
var hiddenElements = Request.Form["ID"]

JQuery changes not reflected in postback

I have two asp:BulletedLists, one is populated on Page_Load and the other is empty. The user can drag and drop < li >'s between them, the meat of that drag-n-drop is
function Move(element, source, target) {
var newLI = document.createElement("li");
var sourceBL = document.getElementById(source);
var targetBL = document.getElementById(target);
newLI.innerHTML = element.innerHTML;
sourceBL.removeChild(element);
targetBL.appendChild(newLI);
}
I create a new element so that it aligns itself within the asp:BulletedList rather than placing itself where the mouse is released.
The problem is I need to know what is where on postback, the second asp:BulletedList is always empty and the first asp:BulletedList populates itself with the original values even though I do not clear or repopulate them.
foreach (ListItem li in blSelectedDocuments.Items) // .Items is empty
{
}
In the past with working with jQuery plugins on ASP.NET WebForms pages, I have used AJAX to send the updated data back to an ASP.NET AJAX Page Method and then stored the changes into Session cache. Then upon postback, the Page_Load would look into the Session to see what order the values in the list were (I had a drag and drop list for the order of display of a report).
Mock code example:
JavaScript:
function Move(element, source, target) {
var newLI = document.createElement("li");
var sourceBL = document.getElementById(source);
var targetBL = document.getElementById(target);
newLI.innerHTML = element.innerHTML;
sourceBL.removeChild(element);
targetBL.appendChild(newLI);
// TODO: Serialize source and target lists to JSON to pass to the server
var serializedData = {};
// Use jQuery.ajax() to call ASP.NET AJAX Page Method
$.ajax({
type: "POST",
url: "PageName.aspx/UpdateListsInSessionCache",
data: serializedData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// Do something here when the AJAX calls completes
}
});
}
ASP.NET Code-behind (C#)
using System.Web.Services;
[WebMethod]
public static void UpdateListsInSessionCache(List<ListItem> source, List<ListItem> target)
{
Session["SourceList"] = source;
Session["TargetList"] = target;
}
protected void Page_Load(object sender, EventArgs e)
{
// Create new lists so we have something empty and not null to work with
var source = new List<ListItem>();
var target = new List<ListItem>();
// Always check for values in Session cache and update if there are values
if (Session["SourceList"] != null)
{
source = Session["SourceList"] as List<ListItem>;
}
if (Session["TargetList"] != null)
{
target = Session["TargetList"] as List<ListItem>;
}
// Do something with source and target lists
}
Horrifically, none of that worked. I'm on SharePoint and the Session wasn't enabled (or whatever) because of some deep dark corner of SharePoint that the asp.config file is located in. Neither did ViewState work in the similar manner. Maybe the AJAX half of that would have worked, but I never got that far.
The solution I got to work was to create a hidden input field, write the order of the asp:BulletedList to that hidden field to go with the postback via the Submit button. Thanks JasonP for serialisation fiddle.
NOTE: I tried some other suggestions I found on the web, using a Label/TextBox with ViewState and/or Readonly properties set did not work for me. Label worked to change text within the page but did not persist on postback.

Categories

Resources