Html.BeginForm in a partial view? - asp.net-mvc-4

I have a block of code that uses the Html.BeginForm to submit a value from textbox to controller. When I put this in a View, it works fine. That is, the controller's action method is called. However, when I place this block of code inside a partial view that will get rendered in the View, the controller's action never gets called.
Not sure if this is the usual behavior or if I am missing something...
#using (Html.BeginForm("TestAction", "Home", FormMethod.Post, new { id = "formId" }))
{<table>
<tr>
<td>Data Date</td>
<td>#Html.TextBox("date")</td>
</tr>
<tr>
<td></td>
<td><input id="btnRun" type="submit" value="submit" /></td>
</tr>
}
Controller:
[HttpPost]
public ActionResult TestAction(string date)
{
[doing something......]
return View();
}
Thanks in advance!

Typically #Html.BeginForm() renders the <form> tag's action to point back to the route details that got it here. Thus in partial views, you're actually rendering back to the outer page. (Yeah, mind-bending.) If you want to specifically direct the form post to a particular route, add additional parameters to the #Html.BeginForm(). See http://msdn.microsoft.com/en-us/library/system.web.mvc.html.formextensions.beginform(v=vs.108).aspx

Related

Showing a substring of text that contains HTML

I am implementing something similar to a blog engine, where on the entry page I would like to see a listing of my posts, and, for each, its title and a short piece of its body content.
This body content is HTML, and is stored in the database as a string, so, it's not enough to just show a substring of it, because it might break the HTML structure.
I guess the algorithm would be: render the string to HTML and extract only the first X characters of it.
Is there any solution for this problem?
Here is a working demo like below:
View:
#model IEnumerable<Post>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Body)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Body)
</td>
</tr>
}
</tbody>
</table>
Controller:
public IActionResult Test()
{
var model = new List<Post>()
{
new Post(){ Title="asp.net core mvc",Body="<html><div><h1>The Model-View-Controller (MVC) architectural pattern separates an application into three main groups of components: Models, Views, and Controllers. This pattern helps to achieve separation of concerns. Using this pattern, user requests are routed to a Controller which is responsible for working with the Model to perform user actions and/or retrieve results of queries. </h1></div></html>"},
new Post(){Title="asp.net core razor pages",Body="<html><div>Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class.</div></html>"}
};
foreach(var item in model)
{
item.Body= Regex.Replace(item.Body, #"<[^>]+>| ", String.Empty);
item.Body= item.Body.AsSpan(0, 30).ToString()+"...";
}
return View(model);
}
Result:

Pass model subset on button click Mvc Core

i am looking to pass through a class from a model subset on button click, this is because i have a model that contains multiple lists of classes that correspond to different datatable. I want to be able to pass one of the classes to a controller on button click or form submit. Below is what i have am aiming for.
#foreach (var item in Model.PersonForm.Where(x => x.PersonType == Utils.PersonTypeEnum.PurchaseType.Owner))
{
<tr>
<th scope="row">#item.Id</th>
<td>#(item.PersonModel.Id)</td>
<td>#(item.PersonModel.Name)</td>
<td>Normal</td>
<td>#($"{item.PersonModel.DOB}")</td>
<td>
<button class="btn-success btn " onclick="location.href='#Url.Action("AcceptPersonJob", "PersonArea",item.PersonModel)'">Accept</button>
</td>
</tr>
}
The 405 error mainly casused by the Http method. The button send a get request, you can put a [HttpGet] attribute on your action. If this is not the case, please show us your controller action and your model.

Display specific data with parameter using Stored Procedure

Hi I have error in regards with my displaying specific data. I passed a parameter through a model and I get error on regarding creating a new instance. here is my code:
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ViewEmployeeSalary(spGetSalaryPerEmployee getsal)
{
var salary = _Context.Set<spGetSalaryPerEmployee>().FromSql("spGetSalaryPerEmployee #empID = {0}", getsal.EmployeeID).AsNoTracking();
return View(salary);
}
View
This the button where you click to redirect to the details page
#foreach(var item in Model)
{
a class="btn btn-primary btn-sm" asp-controller="Salary" asp-action="ViewEmployeeSalary" asp-route-id="#item.EmployeeId"><span class="glyphicon glyphicon-dashboard" style="vertical-align:middle;margin-top: -5px"></span> Salary Details</a>
}
Here is the page where it views the details
#model PEMCOLoan.DAL.Entities.spModels.spGetSalaryPerEmployee
#{
ViewBag.Title = "Salary Details";
}
<h2>#Html.DisplayFor(model => model.FullName)'s Salary Details</h2>
<table class="table">
<tr>
<td class="form-horizontal">ID:</td>
<td>#Html.DisplayTextFor(model => model.EmployeeID)</td>
</tr>
<tr>
<td class="form-horizontal">Salary Amount:</td>
<td>#Html.DisplayFor(model => model.Salary)</td>
</tr>
<tr>
<td class="form-horizontal">Remarks:</td>
<td>#Html.DisplayTextFor(model => model.Remarks)</td>
</tr>
</table>
I get this error:
I don't really what really happens but stated the I need to create an instance.
I have still a little knowledge about asp.net core and ef core and still studying for this language for now. I really need your help in regards with this since I'm a bit new with this language.
Any suggestion would be a greatly appreciated!
Your controller method needs to return single record as error states. Now it returns a list, so you need to change to something like this:
var salary = _Context.Set<spGetSalaryPerEmployee>().FromSql("spGetSalaryPerEmployee #empID = {0}", getsal.EmployeeID).AsNoTracking().SingleOrDefault();
//salary now is single record
return View(salary);
And maybe you need to check salary variable is not null before passing it to view, because then you'll have errors there.

How generate MVC View Controls dynamically?

Is possible to generate controls in View depending on data returned from DB
Example
Model
public string Type{ get; set; }
Controller
public ActionResult Index()
{
return View(db.TypeModel.ToList());
}
View
#model IEnumerable<Sample.Models.TypeModel>
#foreach (var item in Model)
{
<tr>
<td>
#*if Item in model is T generate text box, if C generate text..*#
</td>
</tr>
}
There are multiple solutions to this kind of problem, I personally think that you should take a look in EditorFor html helper.
This method generates different HTML markup depending on the data type
of the property that is being rendered, and according to whether the
property is marked with certain attributes. https://msdn.microsoft.com/en-us/library/system.web.mvc.html.editorextensions.editorfor%28v=vs.118%29.aspx?f=255&MSPPError=-2147217396
Your code can look like this...
#model IEnumerable<Sample.Models.TypeModel>
#foreach (var item in Model)
{
<tr>
<td>
#Html.EditorFor(m=> item.Property,item.Type)
</td>
</tr>
}

Struts1 and ActionForm inheritance, mess of data

I have a problem using Struts1 ActionForm beans. Please, see a part of my struts-config:
<!-- RuleSearchForm is a sublass of RuleForm -->
form-beans>
<form-bean name="ruleForm"
type="forms.RuleForm">
</form-bean>
<form-bean name="ruleSearchForm"
type="forms.RuleSearchForm">
</form-bean>
</form-beans>
<!-- Mappings -->
<action path="/RuleList"
type="actions.RuleList"
name="ruleSearchForm"
scope="session"
validate="false">
<forward name="success" path="/html/view/RuleList.jsp"></forward>
</action>
<action path="/RuleCreate"
type="actions.RuleCreate"
name="ruleForm"
scope="request"
validate="false">
<forward name="success" path="/html/view/CreateUpdateRule.jsp"></forward>
</action>
And parts of my Actionform beans code:
public class RuleForm extends ActionForm {
protected Integer crid;
protected List levels;
/** Some other fileds go here */
public Collection getLevels(){
if(levels == null){
levels = DAOClass.getLevels();
Collections.reverse(levels);
}
return levels;
}
/** Other getters/setters go here */
}
public class RuleSearchForm extends RuleForm{
/**
* Avoid filter reset. If needs to be reset use {#link RuleForm#resetBeanFields()} directly.
* */
public void reset(ActionMapping mapping, HttpServletRequest request) {
}
/**
* Add empty value. User should have an opportunity not to set value for this field.
* */
public Collection getLevels(){
if(levels == null || levels.size() == 0){
super.getLevels();
levels.add(0, new Level());
}
return levels;
}
}
The problem is:
User goes to /RuleList.do and sees the list of rules. ruleSearchForm used as a bean for transferring search params to /RulesList.do action. Initially tihs bean is empty, only getLevels() returns "empty value" + list of levels got from superclass method.
User goes to /CreateRule.do, ruleForm is used for collecting user input. levels property is used in selectbox. And I get there list of levels + empty row. This empty row is not added in RuleForm (named ruleForm). It's added it subclass of RuleForm. Why does super class ActionForm bean with NO static fields, with other name gets values from it's sublass instance???
If users saves Rule and has been redirected to /RuleList.do, the he sees populated (i.e. filled) search form ("ruleSearchForm") with values from "ruleForm".
What does it mean? Please help, I don't understand this mess of data beetween ActionForm Beans
UPD:
Now, I've changed inheritance of FormAction beans. I've introduced BaseFormBean. This BaseFormBean got two children: RuleForm and RuleSearchForm.
It didn't help. Still attributes from one bean are moved to another.
My jsp code:
CreateUpdateRule.jsp:
<html:form action="/RuleSave.do">
<html:hidden property="crid"/>
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td><bean:message key="rule.levelId"/></td>
<td><html:select property="levelId">
<html:optionsCollection property="levels" value="clid" label="name" />
</html:select>
</tr>
<tr>
<td><bean:message key="rule.timeStart"/></td>
<td><html:text property="timeStartStr"/></td>
</tr>
<tr>
<td><bean:message key="rule.timeEnd"/></td>
<td><html:text property="timeEndStr"/></td>
</tr>
<tr>
<td>
<html:submit styleClass="wpsButtonText"><bean:message key="application.submit"/></html:submit>
</td>
<td>
<input type="button" onclick="cancelOperation()" class="wpsButtonText" value="<bean:message key="application.cancel"/>" />
<html:link styleClass="cancelLink" page="/RuleList.do"></html:link>
</td>
</tr>
</table
</html:form>
my RuleList.jsp:
<html:form action="/CritRuleList.do" >
<table style="width: 100%;">
<tr>
<td><bean:message key="rule.levelId"/></td>
<td><html:select property=levelId">
<html:optionsCollection property="levels" value="clid" label="name" />
</html:select>
</td>
</tr>
<tr>
<td><bean:message key="rule.timeStart"/></td>
<td><html:text property="timeStartStr" /></td>
</tr>
<tr>
<td><bean:message key="rule.timeEnd"/></td>
<td><html:text property="timeEndStr" /></td>
</tr>
<tr>
<td colspan="2">
<html:submit styleClass="wpsButtonText"><bean:message key="application.search"/></html:submit>
<input type="button" onclick="cancelOperation(this)" class="wpsButtonText" value="<bean:message key="critrule.searchClear"/>" />
<html:link styleClass="cancelLink" page="/RuleResetSearchFilter.do"></html:link>
</td>
</tr>
</table>
</html:form>
It sounds very strange that a subclass method would be called in the case you've described. To find out why it's happening, you need to debug your code - put a breakpoint inside the if construct of the RuleSearchForm.getLevels() method and see if it is really called (and where did the call originate from).
Other than that, you could try to move the populating logic of levels away from the form(s) altogether, and instead do it in the action. So, in the RuleCreate action you would do something like this:
List levels = DAOClass.getLevels();
Collections.reverse(levels);
request.setAttribute("levels", levels);
This code is really hard to follow, and you still left out or changed some mappings (RuleCreate or CreateRule). My guess would be that you have a misunderstanding in which form declaration is used to populate the fields and the options collection. When you create a form like this
<html:form action="/RuleSave.do">
The values for the select box are taken from the form bean associated with the RuleSave action in your struts-config, not from the form of the action that forwarded to this jsp.
From http://struts.apache.org/1.2.x/userGuide/struts-html.html#form:
Renders an HTML element ... The form bean is located, and created if necessary, based on the form bean specification for the associated ActionMapping.
The [roblem has been resolved.
1. As Tommi said, I've inspected DAO code. DAO returns list of beans kept in static private field.
/**
* Add empty value. User should have an opportunity not to set value for this field.
* */
public Collection getLevels(){
if(levels == null || levels.size() == 0){
super.getLevels();
levels.add(0, new Level());
}
return levels;
}
So each time I add empty bean I do change that static list of objects. Terrible bug.
Params transferring. I've created struts1 app for WebSphere Portal. Portal doesn't have redirect, because I work with portlets, not with pages. That is why request parameters live in request unlit last jsp page is rendered. It has been also solved.