sitefinity update view from action method - sitefinity

I am using this form to post data to the controller once the data is saved I wanted to display this Success view but I am getting a 404 page not found. Any idea why I am getting this error?
View
#using (Html.BeginFormSitefinity("Save", "Preference", FormMethod.Post, new { id = "preferencesForm" }))
{
<div class="row">
<div class="text-center">
<button type="submit" class="btn btn-primary px-4 float-center">Save</button>
</div>
</div>
controller
public ActionResult Save(PreferenceViewModel model)
{
SaveData(model);
return View("~/Mvc/Views/Preference/Success.cshtml");
}

Does your code hit the Save method? I don't see it marked with the [HttpPost] attribute.
Also, if this is your Preference widget, then you can simply use this:
return View("Success");
Sitefinity will look for success.cshtml in the correct folder.

Related

Navigate to new view on button click in ASP.NET Core 3.1 MVC

I am trying to navigate the user to a new page with a button click. I am having issues with rendering the new view. Any time I do click on the button, I either get an error for a dropdown on my page, or I get the home page view but with my desired route in the URL. I wanted to note that the user will be navigating to this page from the home page, which I made into my new landing page on the app. I wanted to point that out in case something I did here can be modified.
How I created a new landing page
I want to navigate from my landing page to my book inventory page.
My View (On the landing page):
<form method="post" asp-controller="Home" asp-action="Home" role="post">
<div class="form-group">
<label asp-for="bookName"></label>
<select name="bookName" asp-items="#(new SelectList(ViewBag.message, "ID", "bookName"))">
</select>
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
</form>
<div class="row">
<div class="form-group">
<a asp-controller="BookInventory" asp-action="Index">
<input type="button" value="Book Inventory Page" />
</a>
</div>
</div>
My Controller (On my landing page)
public void GetBooksDDL()
{
List<BookModel> bookName = new List<BookModel>();
bookName = (from b in _context.BookModel select b).ToList();
bookName.Insert(0, new BookModel { ID = 0, bookName = "" });
ViewBag.message = bookName;
}
[HttpGet("[action]")]
[Route("/Home")]
public IActionResult Home()
{
GetBooksDDL()
return View();
}
My Controller (On my book inventory page):
[HttpGet("[action]")]
[Route("/Index")]
public IActionResult Index()
{
return View();
}
I wanted to note that my breakpoint on my book inventory controller does hit the 'return View()', but it will still render the items from the homepage.
The error I get with the book dropdown says:
ArgumentNullException: Value cannot be null. (Parameter 'items')
Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.ctor(IEnumerable items, string dataValueField, string dataTextField, IEnumerable selectedValues, string dataGroupField).
I'm wondering why I'm getting this error when I'm trying to navigate to a different page. Since this is the new landing page, is it possible that it is passing along all of its data to the rest of the pages?
ArgumentNullException: Value cannot be null. (Parameter 'items')
Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.ctor(IEnumerable
items, string dataValueField, string dataTextField, IEnumerable
selectedValues, string dataGroupField).
About this error, it means that you didn't set the value for the select element, before return to the view, please check the ViewBag.message value, make sure it contains value.
Note: Please remember to check the post method, if the Http Get and Post method returns the same page, make sure you set the ViewBag.message value in both of the action methods.
I wanted to note that my breakpoint on my book inventory controller
does hit the 'return View()', but it will still render the items from
the homepage.
In the BookInventory Controller Index action method, right click and click the "Go to View" option, make sure you have added the Index view.
Based on your code, I have created a sample using the following code, it seems that everything works well.
Code in the Home Controller:
[HttpGet("[action]")]
[Route("/Home")]
public IActionResult Home()
{
GetBooksDDL();
return View();
}
[HttpPost("[action]")]
[Route("/Home")]
public IActionResult Home(BookModel book, string bookName)
{
GetBooksDDL();
//used to set the default selected value, based on the book id (bookName) to find the book.
List<BookModel> booklist = (List<BookModel>)ViewBag.message;
book = booklist.Find(c => c.ID == Convert.ToInt32(bookName));
return View(book);
}
Code in the Home view:
#model BookModel
#{
ViewData["Title"] = "Home";
}
<h1>Home</h1>
<form method="post" asp-controller="Home" asp-action="Home" role="post">
<div class="form-group">
<label asp-for="bookName"></label>
<select name="bookName" asp-items="#(new SelectList(ViewBag.message, "ID", "bookName", Model == null? 0:Model.ID))">
</select>
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
</form>
<div class="row">
<div class="form-group">
<a asp-controller="BookInventory" asp-action="Index">
<input type="button" value="Book Inventory Page" />
</a>
</div>
</div>
Code in the BookInventory controller:
public class BookInventoryController : Controller
{
[HttpGet("[action]")]
[Route("/Index")]
// GET: BookInventory
public ActionResult Index()
{
return View();
}
The screenshot as below:
If still not working, please check your routing configuration, perhaps there have some issue in the routing configure.
Your anchor tag formation is incorrect. You cannot write a button within anchor tag.
Do something like this:
<a asp-action="Index" asp-controller="BookInventory" class="btn btn-primary">Book Inventory Page</a>
Here the class will help your anchor tag look like buttons. I hope you have used bootstrap in your project. If not, then use it.
Hope this helps.
Here is another simple way:
<button type="button" class="btn" onclick="window.location.href = '/YourPage'">Button Title</button>

How to pass a dynamicy changed model to Partial view?

I have a list of "workbooks" displayed in a table. Each workbook has a "Share" button next to the workbook's title. When the user clicks on the share button a modal dialog is shown containing a form.
The form allows the user to enter a list of the recipient's emails separated by a comma which is validated on the client-side.
As the dialog is located in a partial view _ShareView.cshtml that allows me to pass a modal WorkbookShareModel that has some fields like WorkbookId and Title. The goal here is to pass the details of each workbook when the user presses the share button (i.e. construct a modal and pass it to the already rendered model).
I am not sure how to pass a model to an already rendered view?
The solution have to be done on the client (i.e. dont involve actions on the server that return the partial view provided the parameters are passed). I want to avoid unnesessary calls to the server - we have all the data on the client regarding a workbook and I need to do a POST when the user types in list of emails.
This is my index.cshtml:
#section BodyFill
{
<div id="shareFormContainer">
#{ await Html.RenderPartialAsync("_ShareView", new WorkbookShareModel());}
</div>
<div class="landing-container">
<div class="workbook-container">
<table class="table">
<tbody>
#foreach (var workbook in Model.Workbooks)
{
string trClassName, linkText;
if (workbook.Metadata.SharedBy == null)
{
trClassName = "saved-workbooks";
linkText = workbook.Name;
} else {
trClassName = "shared-with-me";
linkText = string.Format(
BaseLanguage.SharedWithMeWorkbook,
workbook.Name,
workbook.Metadata.SharedBy,
workbook.Metadata.SharedDate.ToShortDateString()
);
}
<tr class="#trClassName">
<td>#Html.ActionLink(linkText, "Open", "OpenAnalytics", new { id = Model.Id, workbook = workbook.Name })</td>
<td class="last-modified-date" title="Last Modified Date">#workbook.ModifiedDate.ToShortDateString()</td>
<td class="share">
<button title="Share" class="share-button" onclick='showSharingView("#workbook.Name", "#workbook.Id", "#Model.Id")'> </button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
#section Scripts
{
<!--Load JQuery 'unobtrusive' validation -->
#await Html.PartialAsync("_ValidationScriptsPartial")
<script type="text/javascript">
// hide the modal as soon as the page loads
$('#shareFormModal').modal("hide");
function showSharingView(title, workbookId, id) {
$('#shareFormModal').modal("show");
// how to pass a WorkbookShareModel to my partial view from here?
}
function hideDialog() {
var form = $("#partialform");
// only hide the dialog if the form is valid
if (form.valid()) {
activateShareButtons();
$('#shareFormModal').modal("hide");
}
}
// Helper method that validates list of emails
function IsEmailValid(emailList, element, parameters) {
var SPLIT_REGEXP = /[,;\s]\s*/;
var EMAIL_REGEXP =
/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+##[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/i;
var emails = emailList.split(SPLIT_REGEXP);
for (var i = emails.length; i--;) {
if (!EMAIL_REGEXP.test(emails[i].trim())) {
return false;
}
}
return true;
}
</script>
}
That is my dialog:
#using DNAAnalysisCore.Resources
#model DNAAnalysisCore.Models.WorkbookShareModel
#* Partial view that contains the 'Share Workbook dialog' modal *#
<!-- Modal -->
<div onclick="activateShareButtons()" class="modal fade" id="shareFormModal" role="dialog">
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Share Workbook - #Model.Title</h4>
</div>
#using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post, new { #id = "partialform" }))
{
<div class="modal-body">
<label>#BaseLanguage.Share_workbook_Instruction_text</label>
<div class="form-group">
<textarea class="form-control" asp-for="Emails" rows="4" cols="50" placeholder="#BaseLanguage.ShareDialogPlaceholder"></textarea>
<span asp-validation-for="Emails" class="text-danger"></span>
</div>
<input asp-for="Title" />
<input asp-for="Id" />
<input asp-for="WorkbookId"/>
</div>
<div class="modal-footer">
<button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
<button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
}
</div>
</div>
</div>
There are two solutions to solve your problem :
Option 1 :
Since you have got the parameters(title, workbookId, id) , you can call server side function using AJAX to render the partial view , then replace the DIV contained in the partial view with the updated contents in the callback function of AJAX .
You can click here for code sample .
Option 2 :
Directly update related input/area using Jquery . For example , the input tag helper :
<input asp-for="<Expression Name>">
generates the id and name HTML attributes for the expression name specified in the asp-for attribute. So you can set the value using Jquery like :
$("#Title").val("Title")
Please click here for Tag Helpers in forms in ASP.NET Core
With Option 2 , you need to clear the Emails area firstly after user click the share button ; With Option 1 , you don't need to care that since the HTML will replace entirely .

Not Receiving Multiple Partial View data on Postback

Please can you help on the below query.
I have got a main view and partial view. In main view looping through based on the count of model, the partial views will be rendered. The Partial View is as per below
-----------------Partial View----------------------
#using (Html.BeginCollectionItem("books"))
{
<div id="bookRow" class="bookRow">
<div class='container'>
<div class="align-left">
<h1>Book Name</h1>
<h2>#Html.TextBoxFor(m => m.BookName)</h2>
</div>
<div class="align-right">
<h1>Author</h1>
<h2>#Html.TextBoxFor(m => m.Author)</h2>
</div>
<div class="align-right">
<h1>Publisher</h1>
<h2>#Html.TextBoxFor(m => m.Publisher)</h2>
</div>
<div class="align-right">
#Html.CheckBoxFor(model => model.isConfirm)
#Html.Hidden("Id", #Model.Id)
</div>
Delete
</div>
</div>
}
-------------------Main View----------------------
#model IEnumerable<TDLProject.Models.BookViewModel>
<fieldset>
<legend>Books</legend>
<div id="new-Book">
#foreach (var model in Model)
{
#Html.Partial("_DynamicPartialView", model)
}
</div>
<div>
<input type="button" id="addBook" name="addBook" value="Add Book" />
<br />
</div>
<br />
</fieldset>
#using (Html.BeginForm())
{
<div>
<input type="submit" id="submitButton" value="Submit" />
</div>
}
-------------Controller--------------
[HttpPost]
public ActionResult Contact(IEnumerable<BookViewModel> bookModel)
{
// To do: do whatever you want with the data
return View();
}
The Problem is I am not receiving the data posted from View to the Controller on Click of Submit button. I have multiple partial views of same model on the main view and when click of submit button I need all the partial view data to posted to controller. In Partial View I am using BeginCollectionItem. Please can you help on this.
A form only posts back the name/value pairs of its successful controls, and your not generating the form controls inside the <form> tags.
Change the code to move the #Html.Partial() code inside the <form> (simplified)
#model IEnumerable<TDLProject.Models.BookViewModel>
#using (Html.BeginForm())
{
#foreach (var model in Model)
{
#Html.Partial("_DynamicPartialView", model)
}
<input type="button" id="addBook" name="addBook" value="Add Book" />
<input type="submit" id="submitButton" value="Submit" />
}
You also need to change the POST method signature to
public ActionResult Contact(IEnumerable<BookViewModel> books)
to match the name you use in the #using (Html.BeginCollectionItem("books")) method.

Load link src into iFrame from an asp.net MVC4 controllers action method

created a MVC4 ASP.NET application with razor view
--view code here - iframe and the form with 2 fields on it. Enter ID and click the Search button does invokes the Index Action of the HomeController
#model BusinessApp.Models.SearchViewModel
<iframe id="photomural" name ="mural" src="http://www.mywebfind.com/search" scrolling="yes" width ="75%"> </iframe>
#using (Html.BeginForm("Index", "Home", FormMethod.Get)) {
#Html.ValidationSummary(false)
<fieldset>
<legend>Contact Search </legend>
<div>
#Html.LabelFor(model => model.SomeID)
</div>
<div >
#Html.EditorFor(model => model.SomeID)
#Html.ValidationMessageFor(model => model.SomeID)
</div>
<p>
<input name="SearchButton" type="submit" value="Search" />
</p>
</fieldset>
}
-- based on the user values entered in the search box - the Index action of the home controller is executed.
-- based on some logic that is then executed in the action I would like to have the "src" of the Iframe to be loaded with the link to some website
--CODE in action Method of Home Controller to change the "src" of the IFrame. Could someone please give me some pointers.
public class HomeController : Controller
{
public ActionResult Index(SearchViewModel searchVM)
{
if (searchVM.SomeID != null)
{
//Execute some logic to determine the ID of the URL below that will be passed to Iframe
}
???? Code to change the IFrame src to some url like
"http://OrderManagementSystem/ShowOrder.aspx?ID=10248" based on above logic
return ???
}
}
I appreciate any help I can get from any of the experts out there.
I had the same issue and couldn't find an answer anywhere. Then realized I could set the target in the #using statement to the id of your iframe and return your normal view. Hope this helps someone!
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { target = "photomural"} ))

HttpPost method of PartialView in ASP.NET MVC 4

I have a view that contain two partial views. One of them for creating, and the other is list of created(companies). My problem is that, when I try create HttpPost method does not work and calls only Index method again. Please help me to fix this problem.
This is my Index view
#model InvoiceModel.HelperClasses.CompanyViewModel
#{
ViewBag.Title = "Companies";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="companies">
<div id="create">#Html.Partial("CreateCompany", Model.Create)</div>
<div id="list">#Html.Partial("CompanyTable", Model.Companies)</div>
</div>
Use #Html.BeginForm() to define your Model that you are creating so when you post it is all mapped up properly.
#using (Html.BeginForm("(Action)", "(Controller)", FormMethod.Post, null))
{
(Your model here)
<input type="submit" value="Save" />
}
<div id="list">#Html.Partial("CompanyTable", Model.Companies)</div>