MVC3 Razor Templates - EditorForModel - templates

So, I'm following this article to customise the Html.EditorForModel template. Had it working - fine.
I tried converting it to Razor (Object.cshtml) and get:
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS0115: 'ASP._Page_Views_Shared_EditorTemplates_Object_cshtml.Execute()': no suitable method found to override
Source Error:
Line 44: }
Line 45:
Line 46: public override void Execute() {
Line 47:
Line 48:
Here's the code
#inherits System.Web.Mvc.ViewUserControl
#{ var count = 0; }
#if (ViewData.TemplateInfo.TemplateDepth > 1) {
#ViewData.ModelMetadata.SimpleDisplayText
}
else {
<table class="form">
<tr>
#foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm))) {
if(prop.HideSurroundingHtml) {
#Html.Editor(prop.PropertyName)
}
else {
if(count == 2) {
count = 0;
#:</tr><tr>
}
else {
count++;
}
<td>hi
<div class="editor-label" style="text-align: right;">
#prop.IsRequired ? "*" : ""
#Html.Label(prop.PropertyName)
</div>
</td>
<td>
<div class="editor-field">
#Html.Editor(prop.PropertyName)
#Html.ValidationMessage(prop.PropertyName, "*")
</div>
</td>
}
}
</tr>
</table>
}
I'm out of guesswork.
"Interestingly" when the template is called "_Object.cshtml", #Html.EditorForModel("~/Views/Shared/EditorTemplates/_Object.cshtml") is completely ignored and the default template is used, so knowing why is has to be called "Object" would be a nice to know.

Try removing the first line (the #inherits stuff):
#{ var count = 0; }
#if (ViewData.TemplateInfo.TemplateDepth > 1) {
#ViewData.ModelMetadata.SimpleDisplayText
}
else {
<table class="form">
<tr>
#foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm))) {
if(prop.HideSurroundingHtml) {
#Html.Editor(prop.PropertyName)
}
else {
if(count == 2) {
count = 0;
#:</tr><tr>
}
else {
count++;
}
<td>hi
<div class="editor-label" style="text-align: right;">
#if (prop.IsRequired)
{
#:*
}
#Html.Label(prop.PropertyName)
</div>
</td>
<td>
<div class="editor-field">
#Html.Editor(prop.PropertyName)
#Html.ValidationMessage(prop.PropertyName, "*")
</div>
</td>
}
}
</tr>
</table>
}
Also notice the way I rewrote the #prop.IsRequired test.

Related

Regex for replace a string [duplicate]

I have a string with html markup in it (differMarkup) and would like to run that string through a tokenizer that would identify specific tags (like ins, dels, movs) and replace them with the span tag and add data attributes to it as well.
So the input looks like this:
`<h1>No Changes Here</h1>
<p>This has no changes</p>
<p id="1"><del>Delete </del>the first word</p>
<p id="2"><ins>insertion </ins>Insert a word at the start</p>`
And intended output would be this:
`<h1>No Changes Here</h1>
<p>This has no changes</p>
<p id="1"><span class="del" data-cid=1>Delete</span>the first word</p>
<p id="2"><span class="ins" data-cid=2>insertion</span>Insert a word at the start</p>
`
This is what I currently have. For some reason I'm not able to append the html tags to the finalMarkup var when setting it to span.
const (
htmlTagStart = 60 // Unicode `<`
htmlTagEnd = 62 // Unicode `>`
differMarkup = `<h1>No Changes Here</h1>
<p>This has no changes</p>
<p id="1"><del>Delete </del>the first word</p>
<p id="2"><ins>insertion </ins>Insert a word at the start</p>` // Differ Markup Output
)
func readDifferOutput(differMarkup string) string {
finalMarkup := ""
tokenizer := html.NewTokenizer(strings.NewReader(differMarkup))
token := tokenizer.Token()
loopDomTest:
for {
tt := tokenizer.Next()
switch {
case tt == html.ErrorToken:
break loopDomTest // End of the document, done
case tt == html.StartTagToken, tt == html.SelfClosingTagToken:
token = tokenizer.Token()
tag := token.Data
if tag == "del" {
tokenType := tokenizer.Next()
if tokenType == html.TextToken {
tag = "span"
finalMarkup += tag
}
//And add data attributes
}
case tt == html.TextToken:
if token.Data == "span" {
continue
}
TxtContent := strings.TrimSpace(html.UnescapeString(string(tokenizer.Text())))
finalMarkup += TxtContent
if len(TxtContent) > 0 {
fmt.Printf("%s\n", TxtContent)
}
}
}
fmt.Println("tokenizer text: ", finalMarkup)
return finalMarkup
}
```golang
Basically you want to replace some nodes in your HTML text. For such tasks it's much easier to work with DOMs (Document Object Model) than to handle the tokens yourself.
The package you're using golang.org/x/net/html also supports modeling HTML documents using the html.Node type. To acquire the DOM of an HTML document, use the html.Parse() function.
So what you should do is traverse the DOM, and replace (modify) the nodes you want to. Once you're done with the modifications, you can get back the HTML text by rendering the DOM, for that use html.Render().
This is how it can be done:
const src = `<h1>No Changes Here</h1>
<p>This has no changes</p>
<p id="1"><del>Delete </del>the first word</p>
<p id="2"><ins>insertion </ins>Insert a word at the start</p>`
func main() {
root, err := html.Parse(strings.NewReader(src))
if err != nil {
panic(err)
}
replace(root)
if err = html.Render(os.Stdout, root); err != nil {
panic(err)
}
}
func replace(n *html.Node) {
if n.Type == html.ElementNode {
if n.Data == "del" || n.Data == "ins" {
n.Attr = []html.Attribute{{Key: "class", Val: n.Data}}
n.Data = "span"
}
}
for child := n.FirstChild; child != nil; child = child.NextSibling {
replace(child)
}
}
This will output:
<html><head></head><body><h1>No Changes Here</h1>
<p>This has no changes</p>
<p id="1"><span class="del">Delete </span>the first word</p>
<p id="2"><span class="ins">insertion </span>Insert a word at the start</p></body></html>
This is almost what you want, the "extra" thing is that the html package added wrapper <html> and <body> elements, along with an empty <head>.
If you want to get rid of those, you may just render the content of the <body> element and not the entire DOM:
// To navigate to the <body> node:
body := root.FirstChild. // This is <html>
FirstChild. // this is <head>
NextSibling // this is <body>
// Render everyting in <body>
for child := body.FirstChild; child != nil; child = child.NextSibling {
if err = html.Render(os.Stdout, child); err != nil {
panic(err)
}
}
This will output:
<h1>No Changes Here</h1>
<p>This has no changes</p>
<p id="1"><span class="del">Delete </span>the first word</p>
<p id="2"><span class="ins">insertion </span>Insert a word at the start</p>
And we're done. Try the examples on the Go Playground.
If you want the result as a string (instead of printed to the standard output), you may use bytes.Buffer as the output for rendering, and call its Buffer.String() method in the end:
// Render everyting in <body>
buf := &bytes.Buffer{}
for child := body.FirstChild; child != nil; child = child.NextSibling {
if err = html.Render(buf, child); err != nil {
panic(err)
}
}
fmt.Println(buf.String())
This outputs the same. Try it on the Go Playground.

Vue.js: Inline if-else statement inside <form> with multiple conditions

Is there a way to make inline if-else statement with multiple conditions in Vue?
I have this code in vue:
<template>
<div class = "modal-dialog">
<div class = "modal-header"> <h5>Header</h5></div>
<div class="modal-body">
<form #submit.prevent="editMode ? updateParticipant() : addParticipant()">
/* actual form inside modal body */
</form>
</div>
</div>
</template>
However, I have another boolean variable queryMode. So, I want to also check its value before I execute the methods. More of a nested statement like this:
if(editMode) {
if(queryMode) {
updateParticipant();
} else {
//another method
}
} else {
addParticipant();
}
I have searched about v-if, v-else-if and v-else, but I don't know how to integrate them in my current code structure.
I would have a single handler:
<form #submit.prevent="onSubmit">
with:
methods: {
onSubmit () {
if (this.editMode) {
if (this.queryMode) {
this.updateParticipant();
} else {
//another method
}
} else {
this.addParticipant();
}
}
}
You could, in theory, write it all inline but it would be difficult to read:
<form #submit.prevent="editMode ? queryMode ? updateParticipant() : anotherMethod() : addParticipant()">
You could put some parentheses in but that wouldn't be much better.

Angular 5 form custom validation is not working properly

I am working on Angular 5 and I have a form with a field username. I want to integrate a custom validation for minimum character length and avoid blank space.
<input type="text" class="form-control " id="account-details-username" placeholder="" formControlName="username" >
<div *ngIf="form.get('accountDetails.username').touched && form.get('accountDetails.username').invalid" class="alert alert-danger">
<div *ngIf="form.get('accountDetails.username').errors.required">Username is required.</div>
<div *ngIf="form.get('accountDetails.username').errors.minimumSix">Username must contain at least 6 characters</div>
<div *ngIf="form.get('accountDetails.username').errors.blankSpace">Username does not contain blank space.</div>
</div>
I tried to create a custom method for that. But invoking the first condition only.
test(control: any) {
console.log(control.value);
let minimumSix = new RegExp("^[a-zA-Z0-9!##$%^&*]{6,}");
if (!minimumSix.test(control.value)) {
return { 'minimumSix': true };
}
if(control.value.match("^\\s+$")) {
console.log("blank");
return { 'blankSpace': true };
}
return null;
}
Not checking the blank space validation.
I'd suggest the following solution, when it comes to blanks.
const blankSpace = /^\S*$/;
if (!blankSpace.test(control.value)) {
console.log("blank");
return { 'blankSpace': true };
}
So your full method should look like this:
test(control: any) {
const minimumSix = new RegExp("^[a-zA-Z0-9!##$%^&*]{6,}");
const blankSpace = /^\S*$/;
if (!minimumSix.test(control.value)) {
return { 'minimumSix': true };
}
if (!blankSpace.test(control.value)) {
console.log("blank");
return { 'blankSpace': true };
}
return null;
}

Cannot do the set off process of prepayment with spesific bill using web services in Acumatica

I have a problem in set off processing of Prepayment document with spesific Bill document. It happen only for 1 vendor, because there are a lot of prepayment documents from this vendor (it's about more than 6000 records).
this below is my code.
sCon.getLoginSettlementVoucher(context);
AP301000Content billSchema2 = context.AP301000GetSchema();
List<Command> cmds = new List<Command>();
billSchema2.DocumentSummary.Type.Commit = false;
billSchema2.DocumentSummary.Type.LinkedCommand = null;
var command2 = new Command[]
{
new Value { Value = docTypeSV,
LinkedCommand = billSchema2.DocumentSummary.Type},
new Value { Value = refNbrSV,
LinkedCommand = billSchema2.DocumentSummary.ReferenceNbr},
billSchema2.Applications.DocTypeDisplayDocType,
billSchema2.Applications.ReferenceNbrDisplayRefNbr,
billSchema2.Applications.Balance,
billSchema2.Applications.AmountPaid
};
try
{
var applications = context.AP301000Export(command2, null, 0, false, true);
int rowApp = applications.Count(); int ind = 0;
foreach (var data in applications)
{
string docTypeApp = data[0].ToString();
string refNbrApp = data[1].ToString();
string balanceApp = data[2].ToString();
decimal balApp = Convert.ToDecimal(balanceApp);
string amountPaid = data[3].ToString();
string index = ind.ToString();
if (refNbrApp == AcuRefNbr)
{
billSchema2.DocumentSummary.Type.Commit = false;
billSchema2.DocumentSummary.Type.LinkedCommand = null;
billSchema2.Applications.ReferenceNbrDisplayRefNbr.LinkedCommand = null;
cmds.Add(new Value { LinkedCommand = billSchema2.DocumentSummary.Type, Value = "Bill" });
cmds.Add(new Value { LinkedCommand = billSchema2.DocumentSummary.ReferenceNbr, Value = refNbrSV });
cmds.Add(new Value { LinkedCommand = billSchema2.DocumentSummary.Vendor, Value = vVendCode });
cmds.Add(new Key
{
ObjectName = billSchema2.Applications.DocTypeDisplayDocType.ObjectName,
FieldName = billSchema2.Applications.DocTypeDisplayDocType.FieldName,
Value = docTypeApp
});
cmds.Add(new Key
{
ObjectName = billSchema2.Applications.ReferenceNbrDisplayRefNbr.ObjectName,
FieldName = billSchema2.Applications.ReferenceNbrDisplayRefNbr.FieldName,
Value = refNbrApp
});
cmds.Add(new Value { LinkedCommand = billSchema2.Applications.ServiceCommands.RowNumber, Value = index });
if (docAmtSV == balApp)
cmds.Add(new Value { LinkedCommand = billSchema2.Applications.AmountPaid, Value = docAmountSV });
else if (docAmtSV < balApp)
cmds.Add(new Value { LinkedCommand = billSchema2.Applications.AmountPaid, Value = docAmountSV });
else if (docAmtSV > balApp)
cmds.Add(new Value { LinkedCommand = billSchema2.Applications.AmountPaid, Value = balanceApp });
cmds.Add(billSchema2.Actions.Save);
var result2 = context.AP301000Submit(cmds.ToArray());
}
else
{
continue;
}
}
}
catch (Exception ex)
{
continue;
}
And then I got an exception message like this below in Submit process.
Client found response content type of 'text/html; charset=utf-8', but expected 'text/xml'.
The request failed with the error message:
--
<!DOCTYPE html>
<html>
<head>
<title>Request timed out.</title>
<meta name="viewport" content="width=device-width" />
<style>
body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;}
p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
.marker {font-weight: bold; color: black;text-decoration: none;}
.version {color: gray;}
.error {margin-bottom: 10px;}
.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
#media screen and (max-width: 639px) {
pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
}
#media screen and (max-width: 479px) {
pre { width: 280px; }
}
</style>
</head>
<body bgcolor="white">
<span><H1>Server Error in '/AcuInterface' Application.<hr width=100% size=1 color=silver></H1>
<h2> <i>Request timed out.</i> </h2></span>
<font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">
<b> Description: </b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
<br><br>
<b> Exception Details: </b>System.Web.HttpException: Request timed out.<br><br>
<b>Source Error:</b> <br><br>
<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code>
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.</code>
</td>
</tr>
</table>
<br>
<b>Stack Trace:</b> <br><br>
<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code><pre>
[HttpException (0x80004005): Request timed out.]
</pre></code>
</td>
</tr>
</table>
<br>
<hr width=100% size=1 color=silver>
<b>Version Information:</b> Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1098.0
</font>
</body>
--.
Since the error you are getting is indicating a time out, and that you are only getting it for the one vendor that has around or more than 6000 prepayment documents, you might want to augment the time out value before making your call.
This question here deals with augmenting the time out value for a Screen Based API call : Link.
To resume what is being said there, please use the following line to set the timer to a bigger value.
context.Timeout = 700000;
I already fix this problem, I just have to increase timeout of HttpExecution in web.config file inside of Acumatica ERP instance folder.
..............
..............
by Default Acumatica will set this timeout = 300. It's mean 300 seconds or 5 minutes

MVC 4 - sorting with LINQ doesn't work with Ajax.BeginForm and my For loop

I writing some code with C# and MVC and I have button for sorting a list of data by asc and desc. The logic works in my controller, I am able to call the method that sorts the list and in the breakpoint I can see that it has been sorted.
But it's weird because when I loop through my list in the partial view it never works. I use a breakpoint in my view to make sure it's the same order of items which it is. But it's like the new values don't render to the screen.
TeamManagement.cshtml
#model Website.Models.modelTeamSelect
#{
ViewBag.Title = "Football App";
}
#section featured {
}
#using (Ajax.BeginForm("_PartialTeams",
new
{
model = this.Model
},
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "divCreatedTeams",
InsertionMode = InsertionMode.Replace
}))
{
<div id="divTeams" style="float: left; padding: 10px;">
<h3>Create a new team:</h3>
#Html.LabelFor(m => m.team.TeamName)
#Html.TextBoxFor(m => m.team.TeamName)
<input type="submit" value="Add Team" name="btnSubmit" />
</div>
Html.RenderPartial("~/Views/Partials/_PartialTeams.cshtml");
}
_PartialTeams.cshtml
#model Website.Models.modelTeamSelect
<div id="divCreatedTeams" style="float: left; padding: 10px;">
<h3>Your created teams:</h3>
<input type="submit" value="Asc" name="btnSubmit" />
<input type="submit" value="Desc" name="btnSubmit" />
<br />
#if (Model.teams.Count > 0)
{
for (int i = 0; i < Model.teams.Count; i++)
{
#Html.EditorFor(m => m.teams[i].TeamName)
<input type="button" value="Update team name" name="btnSubmit"/>
<input type="button" value="Remove team" name="btnSubmit"/>
<br />
}
}
</div>
Sorting logic in my controller
[HttpPost]
public PartialViewResult _PartialTeams(string BtnSubmit, modelTeamSelect modelTeamSelect)
{
switch (BtnSubmit)
{
case "Add Team":
modelTeamSelect.teams.Add(modelTeamSelect.team);
break;
case "Asc":
FootballRepository = new Repository.FootballRepository();
modelTeamSelect.teams = FootballRepository.Sort(modelTeamSelect, BtnSubmit);
break;
case "Desc":
FootballRepository = new Repository.FootballRepository();
modelTeamSelect.teams = FootballRepository.Sort(modelTeamSelect, BtnSubmit);
break;
}
return PartialView("~/Views/Partials/_PartialTeams.cshtml", modelTeamSelect);
}
public List<Models.modelTeam> Sort(Models.modelTeamSelect modelTeamSelect, string sort)
{
switch (sort)
{
case "Asc":
modelTeamSelect.teams = modelTeamSelect.teams.OrderBy(t => t.TeamName).ToList();
break;
case "Desc":
modelTeamSelect.teams = modelTeamSelect.teams.OrderByDescending(t => t.TeamName).ToList();
break;
}
return modelTeamSelect.teams;
}
My main model with team collection
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Website.Models
{
public class modelTeamSelect
{
public modelTeamSelect()
{
teams = new List<modelTeam>();
team = new modelTeam();
}
public List<modelTeam> teams { get; set; }
public modelTeam team { get; set; }
}
}
My method Sort does it's job but in the view it never displays correctly. e.g. always wrong order.
Anyone have any ideas because I am stuck.
Screenshots
In the screenshots I click sort by Asc and you can see it says Newcastle as the first item in the list. But when the page renders it will say West Ham first even though it is iterating using the for loop.
All the Html helpers are preferring to use the ModelState values over the actual model values.
So even you have sorted in place your modelTeamSelect.teams in your action in the view #Html.EditorFor(m => m.teams[i].TeamName) call will use the original (before sorting) values form the ModelState.
The solution: if you are updating your action parameters in-place then just clear the ModelState before returning the View/PartialView:
[HttpPost]
public PartialViewResult _PartialTeams(string BtnSubmit,
modelTeamSelect modelTeamSelect)
{
// ... Do the sorting, etc.
ModelState.Clear();
return PartialView("~/Views/Partials/_PartialTeams.cshtml", modelTeamSelect);
}
You can read more about why the helpers are working like this in this article: ASP.NET MVC Postbacks and HtmlHelper Controls ignoring Model Changes