Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • apload-gmbh 39 posts 109 karma points
    Jun 07, 2023 @ 13:54
    apload-gmbh
    0

    Contact Form via Controller

    Hello community

    I'm trying to create a contact form in Umbraco 9 CMS. I tried several solutions, wich all didn't work out. My last attempt was to make a view-file (Kontaktformular.cshtml), a controller (FormController.cs) and an integration in Startup.cs. When i send the form it sais: Could not find a Surface controller route in the RouteTable for controller name FormController. Now am at the point, where I don't know, what else I should do, to make that form work.

    It would be great, if anybody could help me with that. You can see me code below.

    Thank you!

    Startup.cs:

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Routing;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using Serilog;
    using Serilog.Context;
    using System;
    using System.Configuration;
    using System.Diagnostics;
    using Umbraco.Cms.Core.DependencyInjection;
    using Umbraco.Cms.Web.BackOffice.Controllers;
    using Umbraco.Extensions;
    using Microsoft.AspNetCore.Mvc;
    using Umbraco.Cms.Web;
    using Umbraco.Cms.Web.Common.Controllers;
    
    
    namespace Umbraco9.Web
    {
        public class Startup
        {
            private readonly IWebHostEnvironment _env;
            private readonly IConfiguration _config;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="Startup" /> class.
            /// </summary>
            /// <param name="webHostEnvironment">The web hosting environment.</param>
            /// <param name="config">The configuration.</param>
            /// <remarks>
            /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337
            /// </remarks>
            public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
            {
                _env = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
                _config = config ?? throw new ArgumentNullException(nameof(config));
            }
    
            /// <summary>
            /// Configures the services.
            /// </summary>
            /// <param name="services">The services.</param>
            /// <remarks>
            /// This method gets called by the runtime. Use this method to add services to the container.
            /// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            /// </remarks>
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddUmbraco(_env, _config)
                    .AddBackOffice()
                    .AddWebsite()
                    .AddComposers()
                    .Build();
    
                services.AddRouting();
            }
    
            /// <summary>
            /// Configures the application.
            /// </summary>
            /// <param name="app">The application builder.</param>
            /// <param name="env">The web hosting environment.</param>
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {   
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Error");
                    app.UseHsts();
                }
    
                app.UseStatusCodePages();
    
                app.UseUmbraco()
                    .WithMiddleware(u =>
                    {
                        u.UseBackOffice();
                        u.UseWebsite();
                    })
                    .WithEndpoints(u =>
                    {
                        u.UseInstallerEndpoints();
                        u.UseBackOfficeEndpoints();
                        u.UseWebsiteEndpoints();
                    });
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllerRoute(
                        name: "FormController",
                        pattern: "Form/{action}",
                        defaults: new { controller = "FormController", action = "Index" }
                    );
    
                    endpoints.MapControllers();
                });
    
            }
        }
    }
    

    Kontaktformular.cshtml:

    @using Umbraco.Cms.Core.Models
    @using Umbraco.Cms.Web.Common.PublishedModels;
    @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
    @using Microsoft.AspNetCore.Mvc;
    @using Umbraco.Cms.Core.Models.PublishedContent;
    @using Umbraco.Cms.Web.Common.Controllers;
    
    
    @{
        Layout = "Master.cshtml";
    }
    
    <section class="formulate">
        <div class="container">
            @using (Html.BeginUmbracoForm("SubmitForm", "FormController", FormMethod.Post))
            {
                @Html.AntiForgeryToken()
                <fieldset>
                    <div class="form-group">
                        <label for="firstName">Vorname</label>
                        <input
                            type="text"
                            name="firstName"
                            class="form-control"
                            placeholder="Vorname eingeben"
                            value=""
                            required 
                        />
                    </div>
                    <div class="form-group">
                        <label for="lastName">Nachname</label>
                        <input
                            type="text"
                           name="lastName"
                            class="form-control"
                            placeholder="Nachname eingeben"
                            value=""
                            required 
                        />
                    </div>
                    <div class="form-group">
                        <label for="email">E-Mail</label>
                        <input
                            type="email"
                            name="email"
                            class="form-control"
                            placeholder="E-Mail eingeben"
                            value=""
                            required
                        />
                    </div>
                    <div class="form-group">
                        <label for="subject">Betreff</label>
                        <input
                            type="text"
                            name="subject"
                            class="form-control"
                            placeholder="Betreff eingeben"
                            value="" 
                        />
                    </div>
                    <div class="form-group">
                        <label for="message">Nachricht</label>
                        <textarea
                            type="textarea"
                            name="message"
                            class="form-control"
                            value="">
                        </textarea>
                    </div>
                    <button
                        type="submit"
                        name="Submit"
                        value="send"
                        class="btn btn-primary">
                        Senden
                    </button>
                </fieldset>
            }
        </div> <!-- /.container -->
    </section> <!-- /.formulate -->
    

    FormController.cs:

    using System;
    using System.Net;
    using System.Net.Mail;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Umbraco.Cms.Core.Models.PublishedContent;
    using Umbraco.Cms.Core.Routing;
    using Umbraco.Cms.Core.Web;
    using Umbraco.Extensions;
    
    namespace Umbraco9.Web.Controllers
    {
        public class FormController : Controller
        {
            private readonly IUmbracoContextAccessor _umbracoContextAccessor;
            private readonly IPublishedUrlProvider _publishedUrlProvider;
    
            public FormController(IUmbracoContextAccessor umbracoContextAccessor, IPublishedUrlProvider publishedUrlProvider)
            {
                _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
                _publishedUrlProvider = publishedUrlProvider ?? throw new ArgumentNullException(nameof(publishedUrlProvider));
            }
    
            [HttpGet]
            public IActionResult RenderForm()
            {
                return PartialView("ContactForm");
            }
    
            [HttpPost]
            [ValidateAntiForgeryToken]
            public IActionResult SubmitForm(IFormCollection form)
            {
                string firstName = form["firstName"];
                string lastName = form["lastName"];
                string email = form["email"];
                string subject = form["subject"];
                string message = form["message"];
    
                // E-Mail-Einstellungen
                string senderEmail = ""; // Absender-E-Mail-Adresse
                string receiverEmail = ""; // Empfänger-E-Mail-Adresse
                string password = ""; // E-Mail-Passwort
                string smtpHost = "send.smtp.com"; // SMTP-Host
                int smtpPort = 25; // SMTP-Port
    
                // E-Mail erstellen
                MailMessage mail = new MailMessage();
                mail.From = new MailAddress(senderEmail);
                mail.To.Add(receiverEmail);
                mail.Subject = subject;
                mail.Body = $"Name: {firstName} {lastName}\nEmail: {email}\n\n{message}";
    
                // SMTP-Client erstellen und E-Mail senden
                SmtpClient smtpClient = new SmtpClient(smtpHost, smtpPort);
                smtpClient.Credentials = new NetworkCredential(senderEmail, password);
                smtpClient.EnableSsl = true;
                smtpClient.Send(mail);
    
                // Umleitung zur aktuellen Umbraco-Seite
                IPublishedContent currentPage = _umbracoContextAccessor.GetRequiredUmbracoContext().PublishedRequest.PublishedContent;
                string currentPageUrl = _publishedUrlProvider.GetUrl(currentPage, UrlMode.Absolute);
                return Redirect(currentPageUrl);
            }
        }
    }
    
  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    Jun 07, 2023 @ 16:06
    Huw Reddick
    0

    Hi,

    could it be this Html.BeginUmbracoForm("SubmitForm", "FormController", FormMethod.Post) normaly you would just refer to controllers by the name without the controller part, so Html.BeginUmbracoForm("SubmitForm", "Form", FormMethod.Post)

    However this may cause a problem being refered to as Form, propably best to give it a different name, although it may be OK

  • apload-gmbh 39 posts 109 karma points
    Jun 09, 2023 @ 08:06
    apload-gmbh
    0

    Hi Huw

    I also came up with that idea, but it didn't work out.

    But thanks for your help!

  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    Jun 09, 2023 @ 08:10
    Huw Reddick
    100

    try decalring your controller as a surface controller, does that make any difference?

    public class FormController : SurfaceController
    
  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    Jun 09, 2023 @ 08:19
    Huw Reddick
    0

    Another think to try is change the definition of the SubmitForm action, I have just checked some of my code, and in places I had to do this

    SubmitForm([FromForm] IFormCollection formModel)
    

    To determine if that is the issue, you could change it to simple

    `SubmitForm(Object formModel)` 
    

    if it then hits the controller it is the definition that is not correct for the object being passed. If it still doesn't hit the controller action then it is a routing issue. (you should not need to add a route to the startup.cs

  • apload-gmbh 39 posts 109 karma points
    Jun 09, 2023 @ 12:39
    apload-gmbh
    0

    That also didn't work out. So it means, that there is a routing issue in my solution?

  • apload-gmbh 39 posts 109 karma points
    Jun 09, 2023 @ 12:41
    apload-gmbh
    0

    My firts attempt was to create a SurfaceController. But i had to much issues in dependencies and couldn't make it work...

  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    Jun 09, 2023 @ 12:48
    Huw Reddick
    0

    It looks like it yes, one thing to check, when the form is rendered, what is it's action set to?

  • apload-gmbh 39 posts 109 karma points
    Jun 09, 2023 @ 13:30
    apload-gmbh
    0

    In the

    action is just /kontaktformular/.

  • Huw Reddick 1932 posts 6722 karma points MVP 2x c-trib
    Jun 09, 2023 @ 14:28
    Huw Reddick
    0

    That doesn't look right, it should be /Form/SubmitForm if that is your controller an action names.

    I have had this issue before with forms in viewcomponents, try channging your form to the following

    @using (Html.BeginUmbracoForm<FormController>("SubmitForm", null,null,FormMethod.Post))
    
  • apload-gmbh 39 posts 109 karma points
    Jun 12, 2023 @ 07:58
    apload-gmbh
    0

    Hi Huw I tried again to edit my controller to a SurfaceController and now it seems to work! Thank you so much for your help!!!

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies