can i upload a user-selected image to server using web service? - c#

I am doing a ASP .NET website where among other things a user can upload an image, that needs to be saved to the server.
In the whole website I'm trying to accomplish as minimal communication between the client and server as possible. This means that on onload() I invoke web services which return all data needed for that page, and then manipulate them using javascript.
So far, it has worked flawlessly. The problem arises when a user wishes to make changes to his profile. I can take all the information entered in the text fields and the sort, and pass them as arguments to a webservice which saves them to the database. The thing I dont know how to do, or if it is even possible, is to pass the selected image as an argument to the webservice.
I am using html5: <input type="file"> for the image selection

If you use the asp:FileUpload control instead, when the user clicks submit you can do something similar to the following in the page's code-behind:
protected void UploadButton_Click( object sender, EventArgs e ) {
if ( !ImageUpload.HasFile ) {
return;
}
string imageBase64 = System.Convert.ToBase64String( ImageUpload.FileBytes );
YourService service = new YourService();
service.UploadImage( imageBase64 );
This assumes of course that your service has a method called UploadImage that takes a string as a parameter.
Then on the back end, convert the string to a byte array:
byte[] imageArray = System.Convert.FromBase64String( base64ImageData );
And save it as binary data to your database.
As a warning, you may want to add length checks on the webpage to prevent someone from uploading images that are too large... otherwise your server could be bogged down.

You should use a html formular. But you need to change some of the default configuration of the form-tag
<form action="url" method="post" enctype="multipart/form-data">
<input type="file" name="my-file" />
</form>
and you can use an iframe as target of the form, than the page does not reload. You can react on the iframe then...
<form ... target="youriframe">
see this website for a full example

Related

aspx.net uploading files to a server side

I have 2 pages. One page sends an id number that I will use to upload data from database later on.
I send this id number through the url - location += "fileUploadPage.aspx?"+ ID".
Then I need to upload files on the server side on that page. I need the form to not reload the page, as it's removing my URL extension.
I thought about using sessionStorage - but I feel like it's better in my case, as the user can have multiple tabs open for different items to upload files to.
After uploading the file to a server side - I will also need to convert it into a PDF.
I've been trying to do this for a few days and I couldn't fix it.
I managed to upload a file from a form to a server side folder, but I couldn't deny the reload of the page.
When I did deny the reload of the page the server side function did not execute. Also, I have failed to convert into PDF.
I work with aspx.net c# on serverside.
Sadly I can't share the original code as it's on a closed place, but I made a demo on my local pc:
Any suggestions? I'm new to the area of working with files-never done that before. Any suggestions on refactoring my code or how I move the ID is more than welcomed.
The input number is also a text I will need to add to my file name
after converting it to a PDF.
<form id="myForm" name="myForm" action="FilesProblemPage.aspx" runat="server" style="margin-top: 20px;">
<select id="Number" runat="server">
<option value="3">333333333</option>
<option value="2">222222222</option>
</select>
<label runat="server">
click me to choose a file
<input id="uploadFile" name="uploadFile" style="visibility: hidden" type="file" runat="server" />
</label>
<p id="ChosenFile">no file selected</p>
<asp:Button ID="uploadButton" runat="server" Text="Upload" type="button"
OnClick="uploadButton_Click" BorderStyle="None" CssClass="button" />
</form>
let makat = location.href.split("?")[1];
if (makat == 44459999) {
$("#makat").val("workssss");
$(".checkingTemp")[0].checked = true;
$(".checkingTemp")[1].checked = true;
}
$("#body_uploadFile")[0].addEventListener("change", function (e) {
console.log($("#body_uploadFile")[0].files);
if ($("#body_uploadFile")[0].files[0] != undefined)
$("#ChosenFile").text($("#body_uploadFile")[0].files[0].name);
else
$("#ChosenFile").text("no file chosen");
})
server side :
added :
using System.IO;
protected void uploadButton_Click(object sender, EventArgs e)
{
if (uploadFile.PostedFile != null && uploadFile.PostedFile.ContentLength > 0)
{
string fileName = Path.GetFileName(uploadFile.PostedFile.FileName);
string folder = Server.MapPath("~/TempFiles/");
Directory.CreateDirectory(folder);
uploadFile.PostedFile.SaveAs(Path.Combine(folder, fileName));
try
{
Response.Write("<script>alert('operation success')</script>");
}
catch
{
Response.Write("<script>alert('operation failed')</script>");
}
}
}
well, you could still use session() to pass the ID, but then on first page load (on the next page, you save that ID into ViewState. That way, it will not matter if they have multiple pages open since when they jump to the next page, then on first page load IsPostBack = false, then you transfer to ViewState.
ViewState is per web page, were as session() is global. so, pass the id via session, and FIRST thing on next page is to transfer the value to ViewState.
However, the problem with just using a simple FileUpLoad control, is they are not all that great, and if files are larger, then you don't get any kind of progress during the up-load.
For this reason, I tend to spend some REAL efforts on file uploading. (since it is a pain for developers, and often for users alike). There are a LOT of choices in this area, but I was using the AjaxToolKit in my project, and thus adopted that one.
So, users can drag + drop files, or select many files and then hit a up-load button.
the AjaxToolKit up-loader thus looks like this:
So, the user can select a bunch of files - remove them, do whatever.
Then they can hit the up-load button.
Each file uploads - with a progress bar. And then after up-loading, I display the files uploaded.
eg this:
And the other advantage of the up-loader, is there not really a file size limit - it uploads in small chunks.
So, it really depends on how fancy you want to get, but there are quite a few "up-loader" examples and even some jquery + JavaScript ones that are quite nice.
As suggested, if you not using the AjaxControl toolkit, then you could consider it (it a bit over kill - but the toolkit does have a lot of other nice features).
As noted, you might want to better use at least a asp.net FileUpload control, but it depends on how many files, how large, and what kind of UI your looking for here?

Pass Value from View to Controller - MVC

i have a list of thumbnails for the user can select one of the image.
onclick on the thumbnail open a larger image into a form.
What im trying to do now is send the id of the image selected to my controller.
Note: im using MVC 4.
how can i do that?
someone can help with this pls?
Thanks in advance:
Here is my code:
#foreach (var p in ViewBag.Images)
{
<li>
<a href="~/Files/#p.Name" onclick="swap(this); return false;">
<img src="~/Files/#p.Name"/>
</a>
</li>
}
when selected is going this img tag in my form:
<img id="main" src="" >
using this javascript for this event:
function swap(image) {
document.getElementById("main").src = image.href;
}
what i have to do now?
i trying with <input type="hidden" name="Img_Id" value="Viewbag.??????"/>
to pass this value to my controller??
First, some terminology help: You can't pass a value from the view to the controller action, the view is rendered after the controller action completes.
What you want to do is pass data from the client (web browser) to a controller action, using form fields.
In your javascript swap method, you could set the value of the Img_Id field to be the value for the selected image. When the form is submitted, the Img_Id will be posted as form data, and can be accepted as a parameter in the action.
You can use JQuery (or something else) to perform the client side actions.
Here's an example (not tested though!):
First add the ID as a data attribute on the element:
<a href="~/Files/#p.Name" data-id="#p.ID" onclick="swap(this); return false;">
Then some javascript to save that to form (using jquery here):
function swap(image) {
document.getElementById("main").src = image.href;
$("input[name='Img_Id']").val($(image).data("id"));
}
To pass a value back to your controller, you either need to submit a form, or else make an AJAX request to your controller.
In the first case, you'd need to update the value of your hidden field with javascript, and then either wait for the user to submit the form, or trigger a submit through javascript depending on what your needs are.
If you want to do an ajax request, it would be more or less the same thing, but you don't need a hidden field to store the value.
You could use jQuery in your swap function. See here for the official documentation.
If you chose to use this approach, and assuming you place your JavaScript in a separate file, then make sure you get the path for the action and controller and pass that in too.
var url = #Url.Action("Index","Home");
Therefore you may call: onclick="swap(this.id, url)"

Invalid ViewState when using jQuery tabs

I have a fairly simple page with a set of jQuery tabs, the content of some is called via ajax. I also have a search box in the masterpage in my header.
When I open the tabbed page the search box works fine. However once I have clicked on one of the ajax tabs the search box fails to work with an "Invalid Viewstate" yellow screen of death.
I believe this is because the ajax page is replacing the __VIEWSTATE hidden input with its own.
How can I stop this behaviour?
UPDATE: I have noticed that the YSOD only appears in IE and Chrome, Firefox doesn't seem to have the same issue. Although how the browser influences the ViewState, I'm not sure.
UPDATE: I've put a cut down version of the site that shows the issue here: http://dropbox.com/s/7wqgjqqdorgp958/stackoverflow.zip
The reason of such behavior is that you getting content of the ajaxTab.aspx page asynchronously and paste it into another aspx page. So you getting two instances of hidden fields with __VIEWSTATE name and when page posted back to server theirs values are mixing (might depends on how browser process multiple controls with same name on submit). To resolve this you can put second tab's content into a frame:
<div id="tabs">
<ul>
<li>Default Tab</li>
<li>ajax Content</li>
</ul>
<div id="tabs-1">
<p>
To replicate the error:
<ul>
<li>First use the search box top right to search to prove that code is ok</li>
<li>Then click the second ajax tab, and search again.</li>
<li>N.B. Chrome / IE give a state error, Firefox does not</li>
</ul>
</p>
</div>
<iframe id="tabs-2" src="ajaxTab.aspx" style="width:100%;" ></iframe>
</div>
Also, I'm not sure but this seems like error in the Web_UserControls_search control. In my opinion, NavBarSearchItemNoSearchItem_OnClick method must be refactored as below:
protected void NavBarSearchItemNoSearchItem_OnClick(object sender, EventArgs e)
{
var searchFieldTbx = NavBarSearchItemNo;
var navBarSearchCatHiddenField = NavBarSearchCatHiddenField;
var term = searchFieldTbx != null ? searchFieldTbx.Text : "";
if (term.Length > 0) //There is actually something in the input box we can work with
{
//Response.Redirect(Url.GetUrl("SearchResults", term));
Response.Redirect(ResolveClientUrl("~/Web/SearchResults.aspx?term=" + term + "&cat=" + navBarSearchCatHiddenField.Value));
}
}
Draw attention that we resolving client url when redirecting to search results page and instead of navBarSearchCatHiddenField use navBarSearchCatHiddenField.Value as cat parameter.
I guess that you use AJAX to fill the content of the tab. So in this case, content of your tab will be replaced by the new one from ajax and certainly _VIEWSTATE will be replaced. At server, do you use data from ViewState? In the "static tabs", you should prevent them auto reload by using cache:true
Your issue is that with your ajax call you bring in a complete ASPX page. Including the Form tag and its Viewstate. If you remove the Form tag from ajaxTab.aspx you will see everything works fine. asp.net does not know how to handle two Form tags in one page. Same goes for hidden Viewstate fields. You cannot bring in a full aspx page via ajax. Just bring in the content Div you want to display and you`ll be good to go.

Is there a way I continue on with a website while a file is being uploaded?

Background:
I am working on an undergrad research project for my CS department. The project is a website for the biology department and a key feature is that the biology students are able to upload their own .xml files and then a *model is built for them on the server side using Matlab.
The front end is in an ASP.NET, javascript and C# environment. My little association with this project is all the knowledge I have of these systems, tools and languages.
Question:
The .xml files I mentioned earlier can take hours to upload and build. My professor wants the user to be able to continue on with the page using models that are already completed while the new model is sent to the background and the user receives an email when it is completed. I've found material for sending the email, but not for continuing with the page.
I heard something about using AJAX to load a page?
Place a file upload control on your page
<asp:FileUpload ID="FileUpload1" runat="server"/>
Build an http handler to handle the file upload:
public class Handler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
HttpPostedFile fileToUpload = context.Request.Files["Filedata"];
string pathToSave = HttpContext.Current.Server.MapPath("~/Files/")
+ fileToUpload.FileName;
fileToUpload.SaveAs(pathToSave);
//Process file
}
public bool IsReusable {
get {
return false;
}
}
}
Take a look if you can integrate an upload plugin like uploadify into the project(needs jQuery).
<script type = "text/javascript">
$(document).ready(function()
{
$("#<%=FileUpload1.ClientID %>").uploadify(
{
'swf': 'Scripts/uploadify.swf',
'uploader': 'Handler.ashx',
'auto': true,
'buttonText': 'Select File(s)'
});
});
</script>
If you cannot do this, you need to understand how ajax works
Ajax normally uses XMLHttpRequest, which does not allow you encode and send local files to a server.
You could, either use a Flash swf to handle the uploading on the same page, or to use a form that has a target of an invisible 1x1 iframe.
I found the code posted on this blog about file uploads in asp.net
I think having a small i-frame open up, which will actually do the upload, will let your current page continue working.
So on your current page, you ask for file location and file name and all, then open a new page in an i-frame. Let that i-frame know the source file/folder, destination file/folder, and let it work in the background. So now your current page is free to continue its work.
Hope that helps.
Use a headless Java Upload Applet.
Load the file transfer applet in an iFrame, let the user initiate the file transfer and when a user wants to browse the rest of the website, just don't reload the iFrame containing the Java Applet (which will be uploading the file). After the transfer is complete, do a JAvaScript call to close the iframe.
The following example uses a Java Applet by FileCatalyst, but the idea will be practically with any other Java FTP Applet or ActiveX
<script>
var browsePath = "";
function browseAndAdd() {
browsePath = document.FileCatalyst.browseLive(true);
}
function upload() {
document.FileCatalyst.uploadLive();
}
function clearQueue() {
document.FileCatalyst.clearQueue();
}
</script>
<!--Uses onClick for demonstration only-->
<form id="uploadform">
<!--Launch a browse dialog and add the selected file to the queue-->
<input type=button onClick="javascript:browseAndAdd();" value="Browse and Add to Queue" />
<!-- Force upload of whatever is currently found in the transfer queue -->
<input type=button onClick="javascript:upload();" value="Upload">
<!-- Clear transfer queue (can be called only if no transfers are in progress) -->
<input type=button onClick="javascript:clearQueue();" value="Clear Queue">
</form>
Apologies for lack of indentation, I find the stackoverflow markup for inserting code snipets not very user friendly.
You need to set up somekind of asynchronous processing ideally. Personally I like to use Celery and RabbitMQ for my async and messaging.

C#: Open a browser and POST to a url from a windows desktop app

I have a small WPF app (although I guess it doesn't really matter whether it's a wpf form or a webform app?) that I want to have launch a new browser window and POST to a specific url. I've been messing around with:
System.Diagnostics.Process.Start("http://myurl.com");
to launch the window but I don't think I can use the same process to actually post to a url...I've also experimented with HttpWebRequest but I would like the user to be able to use the app after I have posted to this url, not just show them the results...What can I look at to able to do something like this?
There is no direct way to do it. What you could do is generate a HTML page with a form filled with the data you need to post, and a bit of javascript to post the page automatically when it is loaded. Then you just have to open that page in the browser...
The generated HTML could look like that :
<html>
<head>
<script language="Javascript">
function submitForm() {
var theForm = document.getElementById("theForm");
theForm.submit();
}
</script>
</head>
<body onload="submitForm()">
<form id="theForm" action="http://myurl.com" method="POST">
<input type="text" name="username" value="myusername"/>
<input type="password" name="password" value="mypassword"/>
</form>
</body>
</html>
If the page must be displayed in your application, load it in a WebBrowser control
Use the WebBrowser Class instead.
There are multiple solutions, not sure which one would be the best for you...
Proceed with your original approach
Embed web browser control in your applicaiton as suggested in other answers
Do everything programmatically "behind the scene"
For #3 you may want to look here: http://geekswithblogs.net/rakker/archive/2006/04/21/76044.aspx
If you want to go with #1 - it is more tricky, since you need to control external application and different browsers would behave differently.
I've used "javascript:" protocol and the code below with IE as default browser when dealing with one "user-unfriendly" application. Please note that it's not "production-ready" code. There is no error handling, user may shift focus away from launched browser, or use browser without "javascript:" protocol support etc.
static void Main()
{
Settings s = Settings.Default;
Process.Start(s.URL1);
Thread.Sleep(s.Delay1);
SendKeys.SendWait("%D");
Thread.Sleep(100);
SendKeys.SendWait(EncodeForSendKey(s.URL2));
SendKeys.SendWait("{ENTER}");
}
public static string EncodeForSendKey(string value)
{
StringBuilder sb = new StringBuilder(value);
sb.Replace("{", "{{}");
sb.Replace("}", "{}}");
sb.Replace("{{{}}", "{{}");
sb.Replace("[", "{[}");
sb.Replace("]", "{]}");
sb.Replace("(", "{(}");
sb.Replace(")", "{)}");
sb.Replace("+", "{+}");
sb.Replace("^", "{^}");
sb.Replace("%", "{%}");
sb.Replace("~", "{~}");
return sb.ToString();
}
URL1: http://www.google.com
URL2: javascript:function x(){document.all.q.value='stackoverflow';document.forms[0].submit();} x();
You can create a hidden WebBrowser control and do Navigate() (using the overload that allows you to specify the request method). You will need to specify a "_blank" target frame to cause the navigation to happen in a new browser window.

Categories

Resources