Uploaded HttpPostedFileBase Image not displaying after refresh with FileContentResult Action - c#

I am having an issue with the controller action where I upload an image and the initial POSTed result is displayed in the view without issue. The image is shown normally.
If I refresh or change pages and return, the image will no longer display.
I have checked what the controller action is returning, and it does indeed return the content to the view.
This is the IMG tag that I'm using to call the controller action.
<img src="#Url.Action("Display", "Home")" />
This is the controller action:
public ActionResult Display()
{
var tempModel = new PartialModel();
tempModel = (PartialModel)Session["Model"];
var ImageUpload = tempModel.ProductImage;
if (ImageUpload != null)
{
byte[] content = new byte[ImageUpload.ContentLength];
ImageUpload.InputStream.Read(content, 0, ImageUpload.ContentLength);
return File(content, ImageUpload.ContentType);
}
return null;
}
This is the create action that receives the POST values:
public ActionResult Create(PartialModelStore p)
{
Session.RemoveAll();
//m.initializeModelLists(p);
Session["Model"] = p;
//return View("Index", p);
return RedirectToAction("Index");
}
I'm using the Session to store values because this is just a mock up application.
I have looked into using Data URI but I need to support older browsers, thus I'm using this method.

Related

Why does the URL changes to the action name to which I have posted the data?

I have this Controller
[HttpPost]
//[Bind("")]
public ActionResult AddStories(Stories st, HttpPostedFileBase files)
{
try
{
if (files != null)
{
string filePath = Path.Combine(Server.MapPath("~/UploadedFiles/"), Path.GetFileName(files.FileName));
files.SaveAs(filePath);
}
st.Image = Path.GetFileName(files.FileName);
listofStories.Clear();
listofStories = bo.GetAllImages();
if (bo.insertImages(st))
{
ViewBag.Data = "Added";
ViewBag.Grid = listofStories;
ViewBag.Style = "display:none";
ViewBag.StyleAdd = "";
}
else
{
}
}
catch (Exception ex)
{
ViewBag.Data = ex.Message;
}
return View("GetStories", st);
}
and for it, I have a bound partial view which is embedded inside the main view, GetStories.
When I submit data to it then the URL changes to /Stories/AddStories but I want it to be of parent's view such as /Stories/GetStories, after posting the data to AddStories.
I tried several things but nothing works.
I am naive.
When you post, your browser navigates to the post url. There are only two ways to have it show a different url afterwards:
instead of returning the view as though they had hit that url, return a redirect to the preferred url (so the browser does a post followed by a get)
use client-side trickery to change the displayed url - for example replaceState
(browser dependent)
When you posted this question, for example, your browser did a POST to /questions/ask/submit, and the last line of the C# behind that route was a redirect to /questions/46975286/why-does-the-url-changes-to-the-action-name-to-which-i-have-posted-the-data

Redirect to action with JsonResult

I have a view. When user clicks on a button in my view, I am trying to get some data from my view without reloading my view through an AJAX POST to display some data.
This is the method in my controller :
[HttpPost]
public JsonResult GetUserTraj()
{
var userTrajList =
DBManager.Instance.GetUserTraj(Session["UserName"].ToString());
return Json(userTrajList);
}
This returns a Json Result. I am trying to implement session now. So if the session has expired, I want user to be redirected to the Login view. In the above case if the session expires Session["UserName"] becomes null and an exception is raised.
[HttpPost]
public JsonResult GetUserTraj()
{
if (Session["UserName"] != null)
{
var userTrajList =
DBManager.Instance.GetUserTraj(Session["UserName"].ToString());
return Json(userTrajList);
}
else
{
RedirectToAction("Login", "Login");
return Json(null);
}
}
I tried the above code. But it doesn't work. It does not redirect the user to the Login view. I tried return RedirectToAction("Login", "Login");. But that doesn't work since the controller action method cannot return something other than JsonResult. Please help me find a solution for the same.
If you use AJAX to request a page, it's cant redirect in browser.
You should response a status code, and then use javascript to redirect in front, like this
[HttpPost]
public JsonResult GetUserTraj()
{
if (Session["UserName"] != null)
{
var userTrajList =
DBManager.Instance.GetUserTraj(Session["UserName"].ToString());
return Json(userTrajList);
}
else
{
//RedirectToAction("Login", "Login");
return Json(new {code=1});
}
}
You need write this condition Inside of your Ajax success call to reload login screen,
if(result.code ===1){
window.location = 'yourloginpage.html'
}
You can't redirect user to a new page using ajax. For this you have to send some flag at client side and then need to use that flag to identify that session has been expired.
Following code will help you:
[HttpPost]
public JsonResult GetUserTraj()
{
if (Session["UserName"] != null)
{
var userTrajList = DBManager.Instance.GetUserTraj(Session["UserName"].ToString());
return Json(new { Success = true, Data = userTrajList});
}
else
{
return Json(new { Success = false, Message = "Session Expired"});
}
}
jQuery
$.ajax({
url: "any url",
dataType: '',
contentType: "------",
success: function(response){
if(response.Success){
// do stuff
}else{
window.location.href = "/YourLoginURL.aspx"
}
}
});
Just try it
[HttpPost]
public ActionResult GetUserTraj()
{
if (Session["UserName"] != null)
{
var userTrajList =
DBManager.Instance.GetUserTraj(Session["UserName"].ToString());
return Json(userTrajList);
}
else
{
RedirectToAction("Login", "Login");
return Json(null);
}
}
Edit
also your login action should be return json result, if you wont the page reloading
ActionResult is an abstract class that can have several subtypes.
ActionResult Subtypes
ViewResult - Renders a specifed view to the response stream
PartialViewResult - Renders a specifed partial view to the response stream
EmptyResult - An empty response is returned
RedirectResult - Performs an HTTP redirection to a specifed URL
RedirectToRouteResult - Performs an HTTP redirection to a URL that is determined by the
routing engine, based on given route data
JsonResult - Serializes a given ViewData object to JSON format
JavaScriptResult - Returns a piece of JavaScript code that can be executed on the client
ContentResult - Writes content to the response stream without requiring a view
FileContentResult - Returns a file to the client
FileStreamResult - Returns a file to the client, which is provided by a Stream
FilePathResult - Returns a file to the client
Controller
This is a common function may used as a generic one as you wish
public void logoutJson()
{
Response.StatusCode = (int)HttpStatusCode.BadRequest; //Send Error Status to Ajax call
Response.StatusDescription = Url.Action("Index", "Account"); //Url you want to redirect
}
Script
Just paste this code in the View Pages you want to use it. So it will automatically handle All AJAX calls you wanted.
$(document).ready(function () {
$.ajaxSetup({
'complete': function (xhr, textStatus) {
if (xhr.status!="200") {
window.location.replace(xhr.statusText); //Redirect to URL placed in Response.StatusDescription
}
}
});
});
Example
Just call the function for manually fail the AJAX Request and the script in client side handle to redirect to login page.
public JsonResult TestAction()
{
if (null == Session["EmpId"])
{
logoutJson(); //Just call the function
}
}

mvc4 get image in view from controller

First of all, i have used this way in another controller and it works perfectly, now i copied and paste it in another controller, but it didnt work.
i want to get an image from my controller.
i used this code in controller
[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public FileContentResult getPassportImg(int tenantID)
{
byte[] image = db.Tenants.Find(tenantID).passportImage;
if (image != null)
{
return new FileContentResult(image, "image/jpeg");
}
else
{
return null;
}
}
and i make breakpoints throw it and the data is being retrieved correctly.
in the view i do this
<div class="display-field">
<img src="#Url.Action("getPassportImg", "Tenant", new { tenantID = Model.ID })" alt="asdasdf" />
</div>
but when i run my application, it's not get the image. Can you
Please help me resolve this

Why isn't viewbag value passing back to the view?

straight forward question , can't seem to get my viewBag value to display in a view that the user is directed to after completing a form.
Please advise..thanks
My Index ActionResult simple returns model data..
public ActionResult Index()
{
var source = _repository.GetByUserID(_applicationUser.ID);
var model = new RefModel
{
test1 = source.test1,
};
return View(model);
}
My Get Edit" ActionResult , simply uses the same model data as Index.
My Post "Edit" ActionResult, assigns the new values if any to the model and redirects to the Index page, but Index page does not display ViewBag value ??
[HttpPost]
public ActionResult Edit(RefModell model)
{
if (ModelState.IsValid)
{
var source = _repository.GetByUserID(_applicationUser.ID);
if (source == null) return View(model);
source.test1 = model.test1;
_uow.SaveChanges();
#ViewBag.Message = "Profile Updated Successfully";
return RedirectToAction("Index");
}
return View(model);
}
And in my Index view...
#if(#ViewBag.Message != null)
{
<div>
<button type="button">#ViewBag.Message</button>
</div>
}
ViewBag only lives for the current request. In your case you are redirecting, so everything you might have stored in the ViewBag will die along wit the current request. Use ViewBag, only if you render a view, not if you intend to redirect.
Use TempData instead:
TempData["Message"] = "Profile Updated Successfully";
return RedirectToAction("Index");
and then in your view:
#if (TempData["Message"] != null)
{
<div>
<button type="button">#TempData["Message"]</button>
</div>
}
Behind the scenes, TempData will use Session but it will automatically evict the record once you read from it. So it's basically used for short-living, one-redirect persistence storage.
Alternatively you could pass it as query string parameter if you don't want to rely on sessions (which is probably what I would do).
RedirectToAction causes an HTTP 302 response, which makes the client make another call to the server and request a new page.
You should be returning a view instead of redirecting.
The RedirectToAction(msdn) instructs your browser to make a new request.
So your server will be called again but it will be a new request with a blank viewbag and all
You could do a sort of internal redirect by just calling the index method, this way the viewbag will still have its data.
Edit : you'll also have to modify your index method or your View(model) line will try to render the edit. Full code below
public ActionResult Index()
{
var source = _repository.GetByUserID(_applicationUser.ID);
var model = new RefModel
{
test1 = source.test1,
};
return View("Index",model);
}
[HttpPost]
public ActionResult Edit(RefModell model)
{
if (ModelState.IsValid)
{
var source = _repository.GetByUserID(_applicationUser.ID);
if (source == null) return View(model);
source.test1 = model.test1;
_uow.SaveChanges();
#ViewBag.Message = "Profile Updated Successfully";
return Index();
}
return View(model);
}
You can try this way also
Controller
public ActionResult Test()
{
ViewBag.controllerValue= "testvalue";
..................
}
View -
define top of razor page
#{string testvalue= (string)ViewBag.controllerValue;}
$(function () {
var val= '#testvalue';
});

Asp.Net MVC - Blank model not returning blank data

I have a form which a user can fill in x times with the data they want too. The form is posted to the following Action.
[HttpPost]
public ActionResult Manage(ProductOptionModel DataToAdd)
{
if (!ModelState.IsValid)
{
return View(DataToAdd);
}
var ProdServ = new ProductService();
if (DataToAdd.ID != 0)
{
//Edit Mode.
DataToAdd = ProdServ.EditProductOption(DataToAdd);
ViewData["Message"] = "Option Changes Made";
}else
{
//Add
DataToAdd = ProdServ.AddProductOption(DataToAdd);
ViewData["Message"] = "New Option Added";
}
var RetModel = new ProductOptionModel() {ProductID = DataToAdd.ProductID};
return View(RetModel);
}
So at the bottom I blank the model (Leaving just the required field) and then return to the view. However the view holds the data from the previously submitted form.
Any ideas why? I have debugged the code and checked that the RetModel variable is empty.
Html helpers work this way when a view is returned on HTTP POSTs. They prefer post data over model values.
Use Post/Redirect/Get
That's why I suggest you use the Post/Redirect/Get pattern that's very well supported in Asp.net MVC. Your controller actions should redirect to some GET action after POST has successfully completed as it is in your case.
public ActionResult Process()
{
return View(new Data { Id = -1 });
}
[HttpPost]
public ActionResult Process(Data data)
{
if (!this.ModelState.IsValid)
{
return View(data);
}
new MyService().ProcessData(data);
return RedirectToAction("Process");
}
And if you display all previously entered data you can provide those in in the GET action or transfer them from POST to GET action using TempData dictionary.
This is because the build in input helpers will look at the posted data first and use those values if they exist. Then it will look at the model.

Categories