MVC3 View Update Issue - asp.net-mvc-3

Here is a action which sets up the images to ViewBag for display.
public ActionResult UploadPhoto()
{
List<string> images = new List<string>();
foreach (var file in Directory.GetFiles(AlbumManager.GetAlbumName(SessionManager.CurrentSession.PropertyId, true)))
{
images.Add(Server.RelativePath(file));
}
ViewBag.Images = images;
return PartialView("UploadPhoto");
}
Here is a post action which is used to delete the selected image.
[HttpPost]
public ActionResult DeletePhoto(string imageName)
{
AlbumManager.DeletePhoto(SessionManager.CurrentSession.PropertyId, imageName);
return UploadPhoto();
}
As you can see, once the deletion is done, I'm redirecting it to the UploadPhoto action which has to print the currently existing images. But after post-back the deleted image is still displaying. I'm very unsure about this behavior. Please help me to resolve this.
I tried by clearing the model state in DeletePhoto action with following code, but no use.
ModelState.Clear();
My View:
#using (Html.BeginForm("DeletePhoto", "Add", FormMethod.Post, new { id = "PhotoDelete" }))
{
<input type="hidden" name="imageName" id="imageName" />
<div class="thumnailsBox">
#foreach (var image in ViewBag.Images)
{
<div class="thumnailTails">
<span class="thumbimage">
<input id="imageSubmit" type="image" alt="No Image" src="#Url.Content(image)" /></span>
</div>
}
</div>
}
Solution:
In addition to IronMan84's answer, here is the actual solution to my problem:
[HttpPost]
public ActionResult DeletePhoto(string imageName)
{
AlbumManager.DeletePhoto(SessionManager.CurrentSession.PropertyId, imageName);
return JavaScript("location.reload(true)");
}
I'm rendering a script to reload the page here.

You're not redirecting to the UploadPhoto action.
Use RedirectToAction("UploadPhoto"); to redirect.
Also, you can try debugging the code to check if your AlbumManager is not caching your data or not performing the delete.

You're returning a PartialView in UploadPhoto, but your form is not actually targeting a DOM object to update with the result from that PartialView. I would recommend switching to Ajax.BeginForm(), and in your AjaxOptions including the name of the DOM object that you want to update. For more information, try looking at this page.

I'm thinking that MVC is caching your action output from the first method. You should check the documentation for OutputCache, You could try setting NoStore property, and if that didn't work, perhaps a Duration of 0 would prevent caching?

Related

partial views to get data and then post the results to save in database

I am very new to MVC, let me try to explain my scenario in plain simple English:
I have an strongly typed mvc form/page (Product.cshtml) with a model, say ProductViewModel.
This page has got two search buttons, one to search and bring the items to be added to the Product and other to bring in the location, most probably partial views.
Now, what I want is that these search results work in ajax form without complete post back, and then the results of these searches (items and location) should be posted back using model binding to the form when user clicks on the submit button.
What could be the best way of achieving this functionality?
Immediate responses will be well appreciated.
I thought, its good to share the complete code for clarity:
I have one form(Service1.chtml) that has a partial view to display users(_TestUser a partial view:read only), then another partial view(_PlotServiceRequestData) that should have a field to search the plot and bring back the details lke its owner name and landuser etc.
Then when I click on submit button of the main form, I should be able to read all data(main form) + new data from _PlotServiceRequestData partial view and save all data to database.
I was trying one more option, that is, to use #Ajax.ActionLink on Service1.cshtml to call the _GetPlotDetails method and then store partial view data in TempData, so that it is available to the form when users clicks on "Submit" button of Service1.cshtml, is this a right approach?, if I use ajax.BeginForm inside partial view then the data is posted to the
Service1 controller method which is actually to save the form data and not to update the partialview and in this method even I am not getting model data of the partial view.
Sevice1.cshtml:
#model ViewModels.TestViewModel
#{
ViewBag.Title =
"Service1";
}
#
using (Html.BeginForm())
{
#Html.LabelFor(m => m.Title)
#Html.EditorFor(m => m.Title)
#Html.Partial(
"_TestUser", Model)
<div id="RequestPlotData">
#Html.Partial(
"_PlotServiceRequestData", Model.requestData)
</div>
<button type="submit">Save Form</button>
}
#section Scripts {
}
_PlotServiceRequestData.cshtml:
===============================
#model ViewModels.PlotServicesRequestDataViewModel
<
div id="RequestPlotData">
#
using (Ajax.BeginForm("_GetPlotDetails", "Test", new AjaxOptions { UpdateTargetId = "RequestPlotData", Url = Url.Action("_GetPlotDetails","Test") }))
{
<h1>Request Details</h1>
 
<div>
#Html.LabelFor(m => m.plotAddress)
#Html.EditorFor(m => m.plotAddress)
<input type="submit" name="submit" value="Ajax Post" />
</div>
<div>
#Html.LabelFor(m => m.LandUser)
#Html.EditorFor(m => m.LandUser)
</div>
<div>
#Html.LabelFor(m => m.OwnerName)
#Html.EditorFor(m => m.OwnerName)
</div>
}
</
div>
CONTROLLER:
==========
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
namespace
TestNameSpace
{
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Service1()
{
Injazat.AM.mServices.
LocalDBEntities context = new Injazat.AM.mServices.LocalDBEntities();
TestViewModel model =
new TestViewModel() { user = context.Users.First(), Title = "Land Setting Out",
requestData =
new PlotServicesRequestDataViewModel() { ServiceNumber ="122345", TransactionDate="10/10/2033" } };
return View(model);
}
[
HttpPost()]
public ActionResult Service1(TestViewModel model)
{
PlotServicesRequestDataViewModel s = (PlotServicesRequestDataViewModel)TempData[
"Data"];
TestViewModel vm =
new TestViewModel() { user = model.user, requestData = s, Title = model.Title };
return View(vm);
 
}
[
HttpGet()]
//public PartialViewResult _GetPlotDetails(string add)
public PartialViewResult _GetPlotDetails(PlotServicesRequestDataViewModel requestData)
{
//PlotServicesRequestDataViewModel requestData = new PlotServicesRequestDataViewModel() { plotAddress = add};
requestData.OwnerName =
"owner";
requestData.LandUser =
"landuser";
TempData[
"Data"] = requestData;
return PartialView("_PlotServiceRequestData", requestData);
}
}
}
You can probably use the jQuery Form plugin for this. This makes the process of posting the data from your form back to the server very easy. The form would post to an action that would return a partial view that you can then push into your UI.
To make this easier, jQuery form actually has a "target" option where it will automatically update with the server response (ie. the partial view returned from your search action).
View
<form id="searchForm" action="#(Url.Action("Search"))" method="POST">
<input name="query" type="text" /> <!-- order use Html.TextBoxFor() here -->
<input type="submit" />
</form>
<div id="result"><!--result here--></div>
Javascript
$('#searchForm').ajaxForm({
target: '#result'
});
Controller
public ActionResult Search(string query)
{
// Do something with query
var model = GetSearchResults(query);
return Partial("SearchResults", model)
}
This should hopefully help you to get on the right track. jQuery Form is a good plugin and is the main thing you should look into for ajaxifying your form posts back to the server. You might also want to look into using jQuery's $.post and $.ajax functions, but these require slightly more work.

.NET change searched locations web views in MVC4

I'm a newbie in web language.
I started a .NET project on my visual studio 2010, it's in MVC 4 and razor structure.
The problem is that i had an folder in the views folder, with a view in it, but when i try to access the view i got this error:
The view 'searchWeb' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/searchWeb.aspx
~/Views/Home/searchWeb.ascx
~/Views/Shared/searchWeb.aspx
~/Views/Shared/searchWeb.ascx
~/Views/Home/searchWeb.cshtml
~/Views/Home/searchWeb.vbhtml
~/Views/Shared/searchWeb.cshtml
~/Views/Shared/searchWeb.vbhtml
I guess he is not searching in the right folder...but how to change this ?
I looked some topics and apparently i have to make a new viewEngine and inherirted from the old one ?
Is it possible to fix it without making a new view engine ? or can you show me how to make the new view engine ? thank you !
EDIT:
this is my homeController.cs:
namespace Searcher.Controllers
{
public class HomeController : Controller
{
public ActionResult homeWeb()
{
ViewBag.Message = "Searching for sites over the web.";
return View();
}
public ActionResult homeImages()
{
ViewBag.Message = "Searching for images over the web.";
return View();
}
public ActionResult homeVideos()
{
ViewBag.Message = "Searching for videos over the web.";
return View();
}
[HttpPost]
public ActionResult searchWeb()
{
// do something with the search value
return View();
}
}
}
and this is my homeWeb, which is calling the searchWeb:
#{
ViewBag.Title = "Search Web";
}
#section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>#ViewBag.Title.</h1>
<h2>#ViewBag.Message</h2>
</hgroup>
</div>
</section>
}
#using (Html.BeginForm("searchWeb", "Home", FormMethod.Post, new { id = "searchForm" }))
{
<div class="main-block">
<p>
<div>
<input size="200px" type="text" name="searchValue" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</p>
</div>
}
So where is your searchWeb.cshtml file?
Your controller is telling the view engine to look for the search.Web.cshtml file in the Home controller, which normally translates to
~/View/Home/searchWeb.cshtml (one of the default search locations you mentioned in your question).
Its not recomended to change view search location. Trust me:). Especially for newbie in MVC.
And you dont need to change it, this must working from the box.
So make shure that the view location is right. As i can see for this view you need create the action
in Home Controller like
public ActionResult searchWeb()
{
return View();
}
or you trying to call thi view as partial?

Update partial view after edit

I have the following index:
<div id='addProduct'>
#{ Html.RenderPartial("Create", new BoringStore.Models.Product()); }
</div>
<div id='productList'>
#{ Html.RenderPartial("ProductListControl", Model.Products); }
</div>
The partial Create view contains an invisible div which is used to create a new product.
After doing so the partial view ProductListControl is updated.
Now I want to do so with an edit function.
Problem: It's not possible to integrate the edit page while loading the index because at this moment I don't know which product the user wants to edit.
My thought:
I'd like to call my existing edit view in an jquery modal (not the problem) so the user can perform changes.
After saving the modal is closed (still not the problem- I could handle this) and the ProductListControl is updated (here's my problem ... :().
How am I able to do so?
I've seen some tutorials but I'd like to keep it as clean & easy as possible.
Most of them are using dom manipulating and get feedback from the server (controller) by a JsonResult.
If possible I'd like to stick to the razor syntax, no pure JavaScript or jquery and if possible I'd like to avoid JsonResults.
One way might be to use the Ajax.BeginForm for your create product view.
The Ajax.BeginForm accepts a number of AjaxOptions, one being the UpdateTargetId (your DOM id, in this case your productlist div), more info here.
Then in your product controller code you can return a partial view, with the product list. So for example:
Index.cshtml
#using (Ajax.BeginForm("AjaxSave", "Product", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "productList", InsertionMode = InsertionMode.Replace }))
{
// your form
<p>
<input type="submit" value="Save" />
</p>
}
...
<div id="productList">...
</div>
ProductController.cs
[HttpGet]
public ActionResult AjaxSave(Product product)
{
if (ModelState.IsValid)
{
// save products etc..
}
var allProducts = _productService.GetAllProducts();
return PartialView("ProductListControl", allProducts);
}
There is a nice article on about this here.

Ajax.BeginForm not updating target div

Controller:
public ActionResult Edit(string temp)
{
ViewBag.Time = DateTime.Now.ToString("hh:mm:ss");
return PartialView("Edit");
}
Partial View:
#using (Ajax.BeginForm("Edit", "Home", new AjaxOptions{UpdateTargetId = "mydiv"}))
{
<input type="submit" value="Save" />
}
Index View (part of contents)
<div id="mydiv">
<span>The Time is: #ViewBag.Time</span>
</div>
#Html.Partial("Edit")
ClientValidationEnabled and UnobtrusiveJavaScriptEnabled are true
jquery.validate.min.js, jquery.validate.unobtrusive.min.js, jquery.unobtrusive-ajax.min.js, MicrosoftMvcAjax.js and MicrosoftAjax.js are added
At first, the time is shown correctly. When the Save button is clicked for the first time, time disappears and Save button is shown twice and then nothing happens except calling the Action on clicking on both buttons.
You have things kind of backwards. Try this:
Controller
public ActionResult Edit(string temp)
{
ViewBag.Time = DateTime.Now.ToString("hh:mm:ss");
return PartialView("Edit");
}
Index View
#using (Ajax.BeginForm("Edit", "Home", new AjaxOptions{UpdateTargetId = "mydiv"}))
{
<input type="submit" value="Save" />
}
#Html.Action("Edit")
Partial View (Edit)
<div id="mydiv">
<span>The Time is: #ViewBag.Time</span>
</div>
The ViewBag is only accessable at runtime (when the page initially loads) so this means if you fetch data via ajax, the viewbag in the controller action is only accessable to the partial view of that controller action (and not index.cshtml which called the action via ajax). In short (tl;dr) to be able to use the viewbag which you set in Edit action, you need to use it in the returning partialview. (and not anywhere else, because the content isnt re-rendered by the razor engine)
I set things up like so.
Very simple, but I noticed the person posting the
question and the answer had no insertion mode so I posted this lame bit of code :)
{
HttpMethod = "post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "the div youwant to update / replace"
}

MVC3 Razor: how to make a partial view conditionally loaded?

I am beginner in MVC3 and still learning. I try to write an application (MVC3 with Razor) which allows user to select files and upload/save. During upload/save process I want to simply show "wait" text as partial view. I have problem since the partial view is loaded as soon as the web application is started and I got error from HomeController - [HTtpPost] Wait method, since it can't trace the list Files in object job. OF course, the list of Files will be filled after upload. I don't know how to solve this and need your help. Thank you in advance.
My HomeController.cs :
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> attachments)
{
foreach ( var file in attachments )
{
// do something
}
return RedirectToAction("Wait");
}
public ActionResult Wait()
{
// do something
ViewBag.Message = "Wait...";
return View();
}
[HttpPost]
public ActionResult Wait(FormCollection formCollection)
{
Work job = MvcApplication.GetWork();
if ( job.Files.Any() )
{
return RedirectToAction("SubmitWork");
}
else
{
return View();
}
}
The view Index.cshtml :
#{
ViewBag.Title = "FirstTry";
}
<p>
<div id="AddFiles">
#Html.Partial("_AddFiles")
</div>
</p>
<div id ="Wait">
#Html.Partial("_Wait")
</div>
The partial view _Wait.cshtml :
#{
ViewBag.Title = "Wait...";
}
#ViewBag.Message
#using ( Html.BeginForm("Wait", "Home", FormMethod.Post, new
{
id = "waitform"
}) )
{
}
<script type="text/javascript">
window.setTimeout("document.getElementById('waitform').submit()", 1000);
</script>
The partial view _AddFiles.cshtml :
#using ( Html.BeginForm("UploadFile", "Home", FormMethod.Post, new{id = "uploadForm", enctype = "multipart/form-data"}) )
{
#(Html.Telerik().Upload().Name("attachments").Multiple(true)
.Async(async => async.AutoUpload(true) )
)
<input type="submit" value="Send" class="t-button" />
<input type="reset" value="Reset" class="t-button" />
}
MVC does not work like WebForms, client side events will not propagate to server controls (there aren't really even controls, I think Telerik blurs this line a bit and complicates the MVC experience).
You can invoke additional actions in your controller to download HTML or JSON or something, but the only way on the client side to swap HTML without having your page change (since an upload is in progress) would be to use javascript.
I'm not familiar with this Telerik control, but I think you will have to do something on the client side, not on the server side, to indicate loading progress or show a spinner.
Their API shows there is an onupload event you can listen for and possible swap to the loading div:
http://www.telerik.com/help/aspnet-mvc/telerik-ui-components-upload-client-api-and-events.html
They probably have a sample somewhere. I will see if I can dig something up, but really I think just listening for this event is your best bet and do this on the client side, not the server side.

Resources