如何解决Microsoft.Bot.Builder.dll中的“System.Resources.MissingManifestResourceException”

时间:2017-10-02 13:40:09

标签: c# botframework formflow

我使用RView工具在Bot中为FormFlow创建了资源文件,并使用Multilingual App Toolkit(MAT)翻译了字符串。但是每当LuisDialog类调用表单时(在de-DE文化下),它都会在BuildForm()方法中抛出异常'System.Resources.MissingManifestResourceException'

资源文件的名称如下:

Class Hierarchy

抛出异常,BuildForm方法返回FormBuilder()

[Serializable]
public class StandardInfoForm
{
    private DateTime? _startReportDate;
    private DateTime? _endReportDate;
    private static string _reportApplicationsString;
    private static string _reportEmotionsString;


    public string SearchItem { get; set; } //This property is null in case of reporting
    public string Search { get; set; } //This property is null in case of reporting
    public string Application { get; set; } //This property is null in case of reporting
    public string RequestInputType = "Report";
    public string Format = "img";
    public int? FormatWidth = 1024;
    public Report Category { get; set; }

    [Prompt("What kind of report you would like? {||}")]
    public TextReportType? TextReport { get; set; }

    [Prompt("What kind of report you would like? {||}")]
    public ChartReportType? ChartReport { get; set; }

    [Prompt("What is the application name?")]
    public string ReportApplication { get; set; }

    public string[] ReportApplications;

    [Prompt("Please enter applications names seperated by , or enter * for all possible applications")]
    public string ReportApplicationsString
    {
        get
        {
            return _reportApplicationsString;
        }
        set
        {
            _reportApplicationsString = value;
            ReportApplications = _reportApplicationsString?.Split(',');
        }
    }

    [Prompt("Please enter the emotion name? {||}")]
    public Emotion? ReportEmotion { get; set; }

    public string[] ReportEmotions;

    [Prompt("Please enter emotion names seperated by , or enter * for all possible emotions")]
    public string ReportEmotionsString
    {
        get
        {
            return _reportEmotionsString;
        }
        set
        {
            _reportEmotionsString = value;
            ReportEmotions = _reportEmotionsString?.Split(',');
        }
    }

    [Prompt("What kind of chart you would like? {||}")]
    public Chart? FormatChart { get; set;}

    [Prompt("What is starting date (MM-DD-YYYY) for report?")]
    public string StartDate
    {
        get
        {
            return _startReportDate?.ToString("yyyy-MM-dd HH:mm:ss.fff");
        }
        set
        {
            DateTime date;
            DateTime.TryParse(value, out date);
            _startReportDate = date;
        }
    }

    [Prompt("What is the end date (MM-DD-YYYY) for report?")]
    public string EndDate
    {
        get
        {
            return _endReportDate?.ToString("yyyy-MM-dd HH:mm:ss.fff");
        }
        set
        {
            DateTime date;
            DateTime.TryParse(value, out date);
            _endReportDate = date;
        }
    }

    public string ReportRequest = string.Empty;



    public static IForm<StandardInfoForm> BuildForm()
    {            
        var parser = new Parser();
        return new FormBuilder<StandardInfoForm>()
            .Message("Welcome to reporting information!!")
            .Field(nameof(Category))
            .Field(new FieldReflector<StandardInfoForm>(nameof(TextReport))
                .SetActive(state => state.Category == Report.Standard)
                .SetNext(SetNextStandard))
            .Field(new FieldReflector<StandardInfoForm>(nameof(ChartReport))
                .SetActive(state => state.Category == Report.Chart)
                .SetNext(SetNextChart))
            .Field(nameof(ReportApplication), state => 
                {
                    if (state.Category == Report.Standard)
                    {
                        return state.ReportRequest.Contains("application") || state.ReportRequest.Contains("help");
                    }
                    else
                    {
                        return false;
                    }
                })
            .Field(nameof(ReportEmotion), state => 
                {
                    if (state.Category == Report.Standard)
                    {
                        return state.ReportRequest.Contains("emotion");
                    }
                    else
                    {
                        return false;
                    }
                })
            .Field(nameof(ReportApplicationsString), state =>
                {
                    if (state.Category == Report.Chart)
                    {
                        return state.ReportRequest.Contains("application") || state.ReportRequest.Contains("keyboard") || state.ReportRequest.Contains("mouse");
                    }
                    else
                    {
                        return false;
                    }                        
                })
            .Field(nameof(ReportEmotionsString), state =>
                {
                    if (state.Category == Report.Chart)
                    {
                        return state.ReportRequest.Contains("emotion");
                    }
                    else
                    {
                        return false;
                    }
                })
            .Field(nameof(FormatChart), state => 
                {
                    if (state.Category == Report.Chart)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                })
            .Field(nameof(StartDate),
            validate: async (state, response) =>
            {
                var value = (string)response;
                var result = new ValidateResult() { IsValid = false, Feedback = $"{value} is an invalid Start date, Make sure it's correct format and a Past date" };
                var startDate = parser.Parse(value)?.Start ?? DateTime.MaxValue;
                if (DateTime.Compare(DateTime.Today, startDate) >= 0)
                {
                    result.IsValid = true;
                    result.Feedback = null;
                    result.Value = startDate.ToString();
                }
                return result;
            })
            .Field(nameof(EndDate), EndReportDateActive,
            validate: async (state, response) =>
            {
                var value = (string)response;
                var result = new ValidateResult() { IsValid = false, Feedback = $" {value} is an invalid End date, Make sure it's correct format and a Past date" };
                var endDate = parser.Parse(value)?.Start ?? DateTime.MinValue;
                var startDate = state._startReportDate ?? DateTime.MaxValue;
                if (DateTime.Compare(startDate, endDate) <= 0 && DateTime.Compare(DateTime.Today, endDate) >= 0)
                {
                    result.IsValid = true;
                    result.Feedback = null;
                    result.Value = endDate.ToString();
                }
                return result;
            })                              
            .Confirm("Would you like to confirm.Yes or No")
            .Build();
    }

    private static NextStep SetNextChart(object value, StandardInfoForm state)
    {
        var selection = (ChartReportType)value;
        if (selection == ChartReportType.Application)
        {
            state.ReportRequest = "application";
            return new NextStep(new[] { nameof(ReportApplicationsString) });
        }
        else if (selection == ChartReportType.Emotion)
        {
            state.ReportRequest = "emotion";
            return new NextStep(new[] { nameof(ReportEmotionsString) });
        }
        else if (selection == ChartReportType.Keyboard)
        {
            state.ReportRequest = "keyboard";
            return new NextStep(new[] { nameof(ReportApplicationsString) });
        }
        else if (selection == ChartReportType.Mouse)
        {
            state.ReportRequest = "mouse";
            return new NextStep(new[] { nameof(ReportApplicationsString) });
        }
        else if (selection == ChartReportType.Sound)
        {
            state.ReportRequest = "sound";
            return new NextStep(new[] { nameof(FormatChart) });
        }
        else
        {
            return new NextStep();
        }
    }

    private static NextStep SetNextStandard(object value, StandardInfoForm state)
    {
        var selection = (TextReportType)value;
        if (selection == TextReportType.Application)
        {
            state.ReportRequest = "application";
            return new NextStep(new[] { nameof(ReportApplication) });
        }
        else if (selection == TextReportType.Feelings)
        {
            state.ReportRequest = "emotion";
            return new NextStep(new[] { nameof(ReportEmotion) });
        }
        else if (selection == TextReportType.AppVsEmotion)
        {
            state.ReportRequest = "application,emotion";
            return new NextStep(new[] { nameof(ReportApplication) });
        }
        else if (selection == TextReportType.Help)
        {
            state.ReportRequest = "help";
            return new NextStep(new[] { nameof(ReportApplication) });
        }
        else
        {
            return new NextStep();
        }
    }

    public static ActiveDelegate<StandardInfoForm> EndReportDateActive => (state) => !string.IsNullOrWhiteSpace(state.StartDate);

}

堆栈追踪:

    bei Microsoft.Bot.Builder.FormFlow.FormBuilderBase`1.Build(Assembly resourceAssembly, String resourceName)
   bei Microsoft.Bot.Builder.FormFlow.FormBuilder`1.Build(Assembly resourceAssembly, String resourceName)
   bei JoeBot.Forms.StandardInfoForm.BuildForm() in D:\PARIS\JoeBot\Forms\StandardInfoForm.cs:Zeile 152.
   bei Microsoft.Bot.Builder.FormFlow.FormDialog`1..ctor(T state, BuildFormDelegate`1 buildForm, FormOptions options, IEnumerable`1 entities, CultureInfo cultureInfo)
   bei JoeBot.LUISDialogClass.<FindStandardInfo>d__18.MoveNext() in D:\PARIS\JoeBot\Dialogs\LUISDialogClass.cs:Zeile 249.
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.LuisDialog`1.<DispatchToIntentHandler>d__9.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.LuisDialog`1.<MessageReceived>d__8.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.Internals.DialogTask.ThunkResume`1.<Rest>d__5.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Wait`2.<Microsoft-Bot-Builder-Internals-Fibers-IWait<C>-PollAsync>d__19.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Frame`1.<Microsoft-Bot-Builder-Internals-Fibers-IFrameLoop<C>-PollAsync>d__9.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Fiber`1.<Microsoft-Bot-Builder-Internals-Fibers-IFiberLoop<C>-PollAsync>d__16.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei Microsoft.Bot.Builder.Internals.Fibers.Wait`2.Microsoft.Bot.Builder.Internals.Fibers.IAwaiter<T>.GetResult()
   bei JoeBot.RootDialog.<ResumeAfterLUISDialogDialog>d__3.MoveNext() in D:\PARIS\JoeBot\Dialogs\RootDialog.cs:Zeile 122.
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.Internals.DialogTask.ThunkResume`1.<Rest>d__5.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Wait`2.<Microsoft-Bot-Builder-Internals-Fibers-IWait<C>-PollAsync>d__19.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Frame`1.<Microsoft-Bot-Builder-Internals-Fibers-IFrameLoop<C>-PollAsync>d__9.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Fiber`1.<Microsoft-Bot-Builder-Internals-Fibers-IFiberLoop<C>-PollAsync>d__16.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei Microsoft.Bot.Builder.Internals.Fibers.Wait`2.Microsoft.Bot.Builder.Internals.Fibers.IAwaiter<T>.GetResult()
   bei Microsoft.Bot.Builder.Dialogs.Chain.LoopDialog`1.<ResumeAsync>d__3.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.Internals.DialogTask.ThunkResume`1.<Rest>d__5.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Wait`2.<Microsoft-Bot-Builder-Internals-Fibers-IWait<C>-PollAsync>d__19.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Frame`1.<Microsoft-Bot-Builder-Internals-Fibers-IFrameLoop<C>-PollAsync>d__9.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Internals.Fibers.Fiber`1.<Microsoft-Bot-Builder-Internals-Fibers-IFiberLoop<C>-PollAsync>d__16.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.Internals.DialogTask.<Microsoft-Bot-Builder-Base-IEventLoop-PollAsync>d__23.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.Internals.DialogTask.<Microsoft-Bot-Builder-Dialogs-Internals-IDialogStack-Forward>d__17`2.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Bot.Builder.Dialogs.Internals.DialogContext.<Microsoft-Bot-Builder-Dialogs-Internals-IDialogStack-Forward>d__18`2.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   bei JoeBot.RootDialog.<MessageReceivedAsync>d__1.MoveNext() in D:\PARIS\JoeBot\Dialogs\RootDialog.cs:Zeile 79.

1 个答案:

答案 0 :(得分:0)

正如埃里克在评论中所描述的那样。抛出异常是因为resouce文件中缺少某些字符串转换。因此,为了找出缺少哪些字符串,我需要浏览 Microsoft.Bot.Builder.FormFlow 中的SDK代码 以下代码抛出异常,您可以检查 missing.Any()字段的值,以查看缺少字符串的名称。

            if (name != null)
            {
                var rm = new ResourceManager(name, resourceAssembly);
                var rs = rm.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true);
                _form.Localize(rs.GetEnumerator(), out missing, out extra);
                if (missing.Any())
                {
                    throw new MissingManifestResourceException($"Missing resources {missing}");
                }
            }

此博客介绍了如何调试SDK https://blog.botframework.com/2017/07/03/debug-bot-builder-source/